sieve-parser 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/sieve-parser.rb +5 -0
- data/lib/sieve-parser/action.rb +70 -0
- data/lib/sieve-parser/condition.rb +80 -0
- data/lib/sieve-parser/filter.rb +103 -0
- data/lib/sieve-parser/filterset.rb +58 -0
- data/sieve-parser.gemspec +33 -0
- metadata +53 -0
data/lib/sieve-parser.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
module Sieve
|
4
|
+
|
5
|
+
# This class contains the attributes of action
|
6
|
+
class Action
|
7
|
+
attr_accessor :type, :copy, :target, :text
|
8
|
+
|
9
|
+
# Create Action object by text of action
|
10
|
+
#@param [string] text of action
|
11
|
+
#@note Example:
|
12
|
+
# fileinto :copy "INBOX.lixo"
|
13
|
+
#@return [Action] action object parsed
|
14
|
+
def initialize(text=nil)
|
15
|
+
@text = text
|
16
|
+
@type=nil
|
17
|
+
@copy=nil
|
18
|
+
@target=nil
|
19
|
+
parse unless @text.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return a array of actions after parse the text
|
23
|
+
#@note Example:
|
24
|
+
# fileinto "INBOX";
|
25
|
+
# fileinto :copy "INBOX.lixo";
|
26
|
+
# stop;
|
27
|
+
#@param [string] text of actions
|
28
|
+
#@return [Array(Action)] array of Actions
|
29
|
+
def self.parse_all(text)
|
30
|
+
lines = text.split("\n")
|
31
|
+
actions = []
|
32
|
+
lines.each do |line|
|
33
|
+
actions << self.new(line)
|
34
|
+
end
|
35
|
+
actions
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return a text of action
|
39
|
+
#@return [string] text of action
|
40
|
+
def to_s
|
41
|
+
text =""
|
42
|
+
{'type'=>@type, 'copy'=>@copy, 'target'=>@target}.each do |name,item|
|
43
|
+
if ['target'].index(name)
|
44
|
+
text += "\"#{item}\" " unless item.nil?
|
45
|
+
else
|
46
|
+
text += "#{item} " unless item.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
text[text.length-1] = ";"
|
51
|
+
text
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
# Parse text actions to variables of object
|
56
|
+
#@note Example:
|
57
|
+
# @text = %q{fileinto :copy "INBOX.lixo"};
|
58
|
+
def parse
|
59
|
+
[';', '"'].each{|d| @text.delete!(d)}
|
60
|
+
params = @text.split(" ")
|
61
|
+
@type = params[0]
|
62
|
+
if params[1]==":copy"
|
63
|
+
@copy = params[1]
|
64
|
+
@target = params[2]
|
65
|
+
else
|
66
|
+
@target = params[1]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
module Sieve
|
4
|
+
# This class contains the attributes of conditions/tests
|
5
|
+
class Condition
|
6
|
+
attr_accessor :test,:not,:arg1,:arg2,:type, :text
|
7
|
+
|
8
|
+
# Create Condition object by text of condition
|
9
|
+
#@note Example:
|
10
|
+
# header :contains "Subject" "teste"
|
11
|
+
#@param [string] text of condition
|
12
|
+
#@return [Condition] Condition object parsed
|
13
|
+
def initialize(text=nil)
|
14
|
+
@text = text
|
15
|
+
@test=nil
|
16
|
+
@not=nil
|
17
|
+
@arg1=nil
|
18
|
+
@arg2=nil
|
19
|
+
@type=nil
|
20
|
+
parse unless @text.nil?
|
21
|
+
end
|
22
|
+
# Return a array of conditions after parse the text
|
23
|
+
#@param [string] text of conditions
|
24
|
+
#@note Example:
|
25
|
+
# header :contains "From" "all", header :contains "aaaaa" "333"
|
26
|
+
# the text of conditions are splited by ','
|
27
|
+
#@return [Array(Contition)] array of Condition
|
28
|
+
def self.parse_all(text)
|
29
|
+
contitions = []
|
30
|
+
text.scan(/([\s\w:]*\"\S+\"\s\"[\sa-zA-Z0-9,\.\-\@ÁÀÃÂÇÉÈÊÍÌÓÒÔÕÚÙÜÑáàãâçéèêíìóòôõúùüñ]*\")/).each do |item|
|
31
|
+
contitions << self.new(item[0])
|
32
|
+
end
|
33
|
+
contitions
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return a text of action
|
37
|
+
#@return [string] text of action
|
38
|
+
def to_s
|
39
|
+
text =""
|
40
|
+
{"not"=>@not,'test'=>@test,'type'=>@type,'arg1'=>@arg1,'arg2'=>@arg2}.each do |name, item|
|
41
|
+
if ['arg1','arg2'].index(name)
|
42
|
+
text += "\"#{item}\" " unless item.nil?
|
43
|
+
else
|
44
|
+
text += "#{item} " unless item.nil?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
text[text.length-1] = ""
|
48
|
+
text
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
# Parse text condition to variables of object
|
53
|
+
#@note Example:
|
54
|
+
# header :contains "From" "all"
|
55
|
+
def parse
|
56
|
+
if @text =~ /^true/
|
57
|
+
@test = "true"
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
res = @text.scan(/(([\s\w:]+)\"(\S+)\"\s\"([\sa-zA-Z0-9,\.\-\@ÁÀÃÂÇÉÈÊÍÌÓÒÔÕÚÙÜÑáàãâçéèêíìóòôõúùüñ]*)\"|true)/)
|
62
|
+
|
63
|
+
params = res[0][1].strip.split(" ")
|
64
|
+
params += [res[0][2]] + [res[0][3]]
|
65
|
+
|
66
|
+
if params[0] == "not"
|
67
|
+
@not = params[0]
|
68
|
+
@test = params[1]
|
69
|
+
@type = params[2]
|
70
|
+
@arg1 = params[3]
|
71
|
+
@arg2 = params[4]
|
72
|
+
else
|
73
|
+
@test = params[0]
|
74
|
+
@type = params[1]
|
75
|
+
@arg1 = params[2]
|
76
|
+
@arg2 = params[3]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
# This class implements a parse of sieve filter and returns a object
|
3
|
+
# to manipulate
|
4
|
+
# @author Thiago Coutinho<thiago @ osfeio.com>(selialkile)
|
5
|
+
# @note This code folow de "THE BEER-WARE LICENSE"
|
6
|
+
module Sieve
|
7
|
+
class Filter
|
8
|
+
|
9
|
+
#@note [join] can be: any, allof or anyof
|
10
|
+
attr_accessor :name, :type, :join, :text_filter
|
11
|
+
|
12
|
+
# Initialize the class
|
13
|
+
#@param [string] String of filter text
|
14
|
+
#@return [object] Object of self
|
15
|
+
def initialize(text_filter=nil)
|
16
|
+
@text_filter = text_filter
|
17
|
+
@conditions = []
|
18
|
+
@actions = []
|
19
|
+
parse unless @text_filter.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return the conditions of filter
|
23
|
+
#@return [array] conditions
|
24
|
+
def conditions
|
25
|
+
@conditions
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return the actions of filter
|
29
|
+
#@return [array] actions
|
30
|
+
def actions
|
31
|
+
@actions
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return name of filter
|
35
|
+
# @return [string] name of filter
|
36
|
+
def name
|
37
|
+
@name
|
38
|
+
end
|
39
|
+
|
40
|
+
# Add object of Condition to filter
|
41
|
+
#@param [Sieve::Condition]
|
42
|
+
def add_condition(condition)
|
43
|
+
raise "the param is not a Condition" unless condition.class.to_s == "Sieve::Action"
|
44
|
+
@conditions << condition
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return a text of filter
|
48
|
+
#@return [string] text of filter
|
49
|
+
def to_s
|
50
|
+
text = "# #{name}\n"
|
51
|
+
text += "#{@type}"
|
52
|
+
if conditions.count > 1
|
53
|
+
text += " #{@join} (" + conditions.join(", ") + ")"
|
54
|
+
else
|
55
|
+
text += " " + conditions[0].to_s
|
56
|
+
end
|
57
|
+
text += "\n{\n "
|
58
|
+
text += actions.join("\n ")
|
59
|
+
text += "\n}\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
# Parse conditions, call the parse_common or parse_vacation
|
64
|
+
def parse
|
65
|
+
@text_filter[/vacation/].nil? ? parse_common : parse_vacation
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
# Parse the filter adding contitions and actions to class
|
70
|
+
def parse_common
|
71
|
+
#regex_rules_params = "(^#.*)\nif([\s\w\:\"\.\;\(\)\,\-]+)\{([\@\<>=a-zA-Z0-9\s\[\]\_\:\"\.\;\(\)\,\-\/]+)\}$"
|
72
|
+
#regex_rules_params2 = "(^#.*)\n(\S+)(.+)\n\{\n([\s\S]*)\}"
|
73
|
+
parts = @text_filter.scan(/(^#.*)\n(\S+)\s(.+)\n\{\n([\s\S]*)\}/)[0]
|
74
|
+
parse_name(parts[0])
|
75
|
+
@type = parts[1]
|
76
|
+
#if the join is true, dont have conditions...
|
77
|
+
if parts[2] =~ /true/
|
78
|
+
@conditions << Condition.new(type:"true")
|
79
|
+
elsif parts[2] =~ /(anyof|allof)/
|
80
|
+
@join = parts[2][/^\S+/]
|
81
|
+
@conditions.concat(Condition.parse_all( parts[2].scan(/\(([\S\s]+)\)/)[0][0] ))
|
82
|
+
else
|
83
|
+
@conditions << Condition.new(parts[2])
|
84
|
+
end
|
85
|
+
|
86
|
+
@actions.concat(Action.parse_all(parts[3]))
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
# Parse the vacation filter
|
91
|
+
def parse_vacation
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_name(text_name)
|
96
|
+
@name = text_name.match(/#(.*)/)[1].strip
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Vacation
|
101
|
+
attr_accessor :days, :subject, :content
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
# This class implements a parse of sieve and returns a object
|
4
|
+
# to manipulate
|
5
|
+
# ONLY ACCEPTY THE "IF" conditions
|
6
|
+
#@see http://www.faqs.org/rfcs/rfc3028.html
|
7
|
+
#@see http://www.faqs.org/rfcs/rfc5804.html
|
8
|
+
#@see http://www.faqs.org/rfcs/rfc5230.html
|
9
|
+
#@see http://www.faqs.org/rfcs/rfc5229.html
|
10
|
+
# @author Thiago Coutinho<thiago @ osfeio.com>(selialkile)
|
11
|
+
# @author Thiago Coutinho<thiago.coutinho@locaweb.com.br>
|
12
|
+
# @note This code folow de "THE BEER-WARE LICENSE"
|
13
|
+
|
14
|
+
module Sieve
|
15
|
+
class FilterSet
|
16
|
+
attr_accessor :text_sieve
|
17
|
+
|
18
|
+
def initialize(text_sieve=nil)
|
19
|
+
@text_sieve = text_sieve
|
20
|
+
@requires = []
|
21
|
+
@filters = []
|
22
|
+
parse unless @text_sieve.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return all filters of script.
|
26
|
+
#@return [array] array of filters
|
27
|
+
def filters
|
28
|
+
@filters
|
29
|
+
end
|
30
|
+
|
31
|
+
# Requires inside the script
|
32
|
+
#@return [array] names of requires
|
33
|
+
def requires
|
34
|
+
@requires
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return a text of filterset
|
38
|
+
#@return [string] text of filterset
|
39
|
+
def to_s
|
40
|
+
text = "require [\"#{requires.join('","')}\"];\n"
|
41
|
+
text += filters.join("")
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
# Make de parse and put results in variables
|
46
|
+
def parse
|
47
|
+
#return a array with string of elements: "xxxx", "yyyyyy"
|
48
|
+
@text_sieve.scan(/^require\s\["(\S+)"\];$/).each do |r|
|
49
|
+
@requires.concat(r[0].split('","'))
|
50
|
+
end
|
51
|
+
|
52
|
+
@text_sieve.scan(/(^#.*\nif[\s\w\:\"\.\;\(\)\,\-]*\n\{[a-zA-Z0-9\s\@\<>=\:\[\]\_\"\.\;\(\)\,\-\/]*\n\}$)/).each do |f|
|
53
|
+
@filters << Sieve::Filter.new(f[0])
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'sieve-parser'
|
5
|
+
s.version = '0.0.1'
|
6
|
+
s.summary = 'A Ruby library for sieve parser'
|
7
|
+
s.description = <<-EOF
|
8
|
+
sieve-parser is a pure-ruby implementation for parsing and
|
9
|
+
manipulate the sieve scripts.
|
10
|
+
EOF
|
11
|
+
s.requirements << 'A sieve script to parse and gem ruby-managesieve to connect on server.'
|
12
|
+
s.files = [
|
13
|
+
'lib/sieve-parser',
|
14
|
+
'lib/sieve-parser/action.rb',
|
15
|
+
'lib/sieve-parser/condition.rb',
|
16
|
+
'lib/sieve-parser/filter.rb',
|
17
|
+
'lib/sieve-parser/filterset.rb',
|
18
|
+
'lib/sieve-parser.rb',
|
19
|
+
'sieve-parser.gemspec'
|
20
|
+
]
|
21
|
+
|
22
|
+
s.has_rdoc = true
|
23
|
+
s.author = 'Thiago Coutinho'
|
24
|
+
s.email = 'thiago.coutinho@locaweb.com.br'
|
25
|
+
s.rubyforge_project = 'sieve-parser'
|
26
|
+
s.homepage = "http://github.com/selialkile/sieve-parser"
|
27
|
+
end
|
28
|
+
|
29
|
+
if __FILE__ == $0
|
30
|
+
Gem::Builder.new(spec).build
|
31
|
+
else
|
32
|
+
spec
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sieve-parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thiago Coutinho
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-25 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! " sieve-parser is a pure-ruby implementation for parsing and \n
|
15
|
+
\ manipulate the sieve scripts.\n"
|
16
|
+
email: thiago.coutinho@locaweb.com.br
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/sieve-parser/action.rb
|
22
|
+
- lib/sieve-parser/condition.rb
|
23
|
+
- lib/sieve-parser/filter.rb
|
24
|
+
- lib/sieve-parser/filterset.rb
|
25
|
+
- lib/sieve-parser.rb
|
26
|
+
- sieve-parser.gemspec
|
27
|
+
homepage: http://github.com/selialkile/sieve-parser
|
28
|
+
licenses: []
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements:
|
46
|
+
- A sieve script to parse and gem ruby-managesieve to connect on server.
|
47
|
+
rubyforge_project: sieve-parser
|
48
|
+
rubygems_version: 1.8.15
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: A Ruby library for sieve parser
|
52
|
+
test_files: []
|
53
|
+
has_rdoc: true
|