///|
pub fn allowed(text : String, agent : String, path : String) -> Bool {
decide(parse(text), agent, path).allowed
}
///|
pub fn decide(robots : Robots, agent : String, path : String) -> Decision {
let normalized = normalize_path(path)
match best_group(robots, agent) {
Some(group) => decide_group(group, agent, normalized)
None =>
{
allowed: true,
agent,
path: normalized,
matched_kind: "none",
matched_pattern: "",
}
}
}
///|
pub fn best_group(robots : Robots, agent : String) -> Group? {
let mut best : Group? = None
let mut best_score = -1
for group in robots.groups {
let score = group_agent_score(group, agent)
if score > best_score {
best = Some(group)
best_score = score
}
}
if best_score >= 0 {
best
} else {
None
}
}
///|
pub fn decide_group(group : Group, agent : String, path : String) -> Decision {
let mut matched : Rule? = None
let mut best_len = -1
for rule in group.rules {
if rule_matches(rule, path) {
let weight = rule_weight(rule)
if weight > best_len {
matched = Some(rule)
best_len = weight
} else if weight == best_len &&
matched is Some(old) &&
is_allow(rule) &&
!is_allow(old) {
matched = Some(rule)
}
}
}
match matched {
Some(rule) =>
{
allowed: is_allow(rule),
agent,
path,
matched_kind: rule.kind,
matched_pattern: rule.pattern,
}
None =>
{ allowed: true, agent, path, matched_kind: "none", matched_pattern: "" }
}
}
///|
pub fn rule_matches(rule : Rule, path : String) -> Bool {
pattern_matches(rule.pattern, path)
}
///|
pub fn pattern_matches(pattern : String, path : String) -> Bool {
if pattern == "" {
return false
}
if pattern == "/" {
return true
}
if pattern.has_suffix("$") {
let base = pattern.unsafe_substring(start=0, end=pattern.length() - 1)
return wildcard_prefix_match(base, path) && wildcard_suffix_ok(base, path)
}
wildcard_prefix_match(pattern, path)
}
///|
pub fn wildcard_prefix_match(pattern : String, path : String) -> Bool {
if pattern.find("*") is None {
return path.has_prefix(pattern)
}
let pieces = split_char(pattern, '*')
let mut offset = 0
let mut first = true
for piece in pieces {
if piece == "" {
first = false
continue
}
if first {
if !path.has_prefix(piece) {
return false
}
offset = piece.length()
} else {
match path.unsafe_substring(start=offset, end=path.length()).find(piece) {
Some(found) => offset = offset + found + piece.length()
None => return false
}
}
first = false
}
true
}
///|
pub fn wildcard_suffix_ok(pattern : String, path : String) -> Bool {
let pieces = split_char(pattern, '*')
for index = pieces.length() - 1; index >= 0; index = index - 1 {
let piece = pieces[index]
if piece != "" {
return path.has_suffix(piece)
}
}
true
}
///|
pub fn decision_line(decision : Decision) -> String {
let verdict = if decision.allowed { "allow" } else { "disallow" }
verdict +
" " +
decision.path +
" by " +
decision.matched_kind +
":" +
decision.matched_pattern
}