carps 0.2.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.
Files changed (157) hide show
  1. data/COPYING +674 -0
  2. data/GEM_DESCRIPTION +10 -0
  3. data/History.txt +4 -0
  4. data/Manifest.txt +156 -0
  5. data/PostInstall.txt +20 -0
  6. data/README.rdoc +141 -0
  7. data/Rakefile +28 -0
  8. data/bin/carps +123 -0
  9. data/bin/carps_init +29 -0
  10. data/bin/carps_ipc_test +44 -0
  11. data/bin/carps_mod_saver_test +71 -0
  12. data/bin/carps_mod_test +62 -0
  13. data/config/website.yml +2 -0
  14. data/features/character_sheet.feature +40 -0
  15. data/features/crash.feature +15 -0
  16. data/features/crypt.feature +22 -0
  17. data/features/dice.feature +173 -0
  18. data/features/dm.feature +36 -0
  19. data/features/dmll.feature +51 -0
  20. data/features/edit.feature +10 -0
  21. data/features/email.feature +29 -0
  22. data/features/interface.feature +17 -0
  23. data/features/ipc.feature +10 -0
  24. data/features/mailbox.feature +33 -0
  25. data/features/mod.feature +31 -0
  26. data/features/parser.feature +9 -0
  27. data/features/persistent_protocol.feature +14 -0
  28. data/features/player.feature +22 -0
  29. data/features/player_turn.feature +29 -0
  30. data/features/random.feature +15 -0
  31. data/features/rule.feature +19 -0
  32. data/features/safety.feature +13 -0
  33. data/features/sessions.feature +16 -0
  34. data/features/start_dm.feature +18 -0
  35. data/features/start_player.feature +8 -0
  36. data/features/step_definitions/common_steps.rb +170 -0
  37. data/features/steps/character_sheet.rb +89 -0
  38. data/features/steps/crash.rb +27 -0
  39. data/features/steps/crypt.rb +166 -0
  40. data/features/steps/dice.rb +91 -0
  41. data/features/steps/dm.rb +147 -0
  42. data/features/steps/dmll.rb +47 -0
  43. data/features/steps/edit.rb +7 -0
  44. data/features/steps/email.rb +108 -0
  45. data/features/steps/general.rb +5 -0
  46. data/features/steps/interface.rb +64 -0
  47. data/features/steps/ipc.rb +22 -0
  48. data/features/steps/mailbox.rb +126 -0
  49. data/features/steps/mod.rb +25 -0
  50. data/features/steps/parser.rb +23 -0
  51. data/features/steps/persistent_protocol.rb +29 -0
  52. data/features/steps/player.rb +82 -0
  53. data/features/steps/player_turn.rb +56 -0
  54. data/features/steps/random.rb +47 -0
  55. data/features/steps/rule.rb +53 -0
  56. data/features/steps/safety.rb +17 -0
  57. data/features/steps/sessions.rb +37 -0
  58. data/features/steps/start_dm.rb +46 -0
  59. data/features/steps/start_player.rb +65 -0
  60. data/features/steps/timeout.rb +32 -0
  61. data/features/steps/type_verification.rb +36 -0
  62. data/features/steps/wizard.rb +123 -0
  63. data/features/support/common.rb +29 -0
  64. data/features/support/env.rb +14 -0
  65. data/features/support/matchers.rb +11 -0
  66. data/features/timeout.feature +11 -0
  67. data/features/type_verification.feature +48 -0
  68. data/features/wizard.feature +50 -0
  69. data/lib/carps/crypt/accept_handshake.rb +40 -0
  70. data/lib/carps/crypt/default_messages.rb +29 -0
  71. data/lib/carps/crypt/handshake.rb +41 -0
  72. data/lib/carps/crypt/mailbox.rb +265 -0
  73. data/lib/carps/crypt/mailer.rb +220 -0
  74. data/lib/carps/crypt/peer.rb +123 -0
  75. data/lib/carps/crypt/public_key.rb +60 -0
  76. data/lib/carps/crypt.rb +23 -0
  77. data/lib/carps/email/config.rb +122 -0
  78. data/lib/carps/email/imap.rb +156 -0
  79. data/lib/carps/email/smtp.rb +119 -0
  80. data/lib/carps/email/string.rb +30 -0
  81. data/lib/carps/email.rb +21 -0
  82. data/lib/carps/mod/action.rb +36 -0
  83. data/lib/carps/mod/answers.rb +76 -0
  84. data/lib/carps/mod/client_turn.rb +88 -0
  85. data/lib/carps/mod/dice.rb +360 -0
  86. data/lib/carps/mod/dm/interface.rb +160 -0
  87. data/lib/carps/mod/dm/mod.rb +409 -0
  88. data/lib/carps/mod/dm/reporter.rb +112 -0
  89. data/lib/carps/mod/dm/resource.rb +88 -0
  90. data/lib/carps/mod/dm/room.rb +33 -0
  91. data/lib/carps/mod/interface.rb +73 -0
  92. data/lib/carps/mod/launch.rb +108 -0
  93. data/lib/carps/mod/mod.rb +52 -0
  94. data/lib/carps/mod/player/interface.rb +76 -0
  95. data/lib/carps/mod/player/mod.rb +109 -0
  96. data/lib/carps/mod/question.rb +63 -0
  97. data/lib/carps/mod/rule.rb +112 -0
  98. data/lib/carps/mod/sheet/character.rb +82 -0
  99. data/lib/carps/mod/sheet/editor.rb +97 -0
  100. data/lib/carps/mod/sheet/new_sheet.rb +71 -0
  101. data/lib/carps/mod/sheet/schema.rb +84 -0
  102. data/lib/carps/mod/sheet/type.rb +161 -0
  103. data/lib/carps/mod/sheet/verifier.rb +41 -0
  104. data/lib/carps/mod/status_report.rb +51 -0
  105. data/lib/carps/mod.rb +40 -0
  106. data/lib/carps/protocol/keyword.rb +104 -0
  107. data/lib/carps/protocol/message.rb +138 -0
  108. data/lib/carps/protocol.rb +19 -0
  109. data/lib/carps/service/client_parser.rb +34 -0
  110. data/lib/carps/service/dm/config.rb +76 -0
  111. data/lib/carps/service/dm/mailer.rb +70 -0
  112. data/lib/carps/service/dm/new_game.rb +101 -0
  113. data/lib/carps/service/dm/start.rb +47 -0
  114. data/lib/carps/service/game.rb +101 -0
  115. data/lib/carps/service/interface.rb +174 -0
  116. data/lib/carps/service/invite.rb +79 -0
  117. data/lib/carps/service/mod.rb +43 -0
  118. data/lib/carps/service/player/config.rb +78 -0
  119. data/lib/carps/service/player/mailer.rb +49 -0
  120. data/lib/carps/service/player/start.rb +60 -0
  121. data/lib/carps/service/server_parser.rb +33 -0
  122. data/lib/carps/service/session.rb +96 -0
  123. data/lib/carps/service/start/config.rb +71 -0
  124. data/lib/carps/service/start/interface.rb +101 -0
  125. data/lib/carps/service/start/mailer.rb +46 -0
  126. data/lib/carps/service.rb +35 -0
  127. data/lib/carps/test.rb +34 -0
  128. data/lib/carps/ui/colour.rb +28 -0
  129. data/lib/carps/ui/error.rb +39 -0
  130. data/lib/carps/ui/highlight.rb +32 -0
  131. data/lib/carps/ui/question.rb +63 -0
  132. data/lib/carps/ui/warn.rb +37 -0
  133. data/lib/carps/ui.rb +21 -0
  134. data/lib/carps/util/config.rb +162 -0
  135. data/lib/carps/util/editor.rb +147 -0
  136. data/lib/carps/util/error.rb +75 -0
  137. data/lib/carps/util/files.rb +48 -0
  138. data/lib/carps/util/init.rb +93 -0
  139. data/lib/carps/util/process.rb +150 -0
  140. data/lib/carps/util/timeout.rb +31 -0
  141. data/lib/carps/util/windows.rb +29 -0
  142. data/lib/carps/util.rb +24 -0
  143. data/lib/carps/wizard/dm.rb +41 -0
  144. data/lib/carps/wizard/player.rb +40 -0
  145. data/lib/carps/wizard/steps.rb +494 -0
  146. data/lib/carps/wizard/wizard.rb +126 -0
  147. data/lib/carps/wizard.rb +21 -0
  148. data/lib/carps.rb +45 -0
  149. data/permission +16 -0
  150. data/script/console +10 -0
  151. data/script/destroy +14 -0
  152. data/script/generate +14 -0
  153. data/tasks/readme_site.rake +28 -0
  154. data/test/test_carps.rb +11 -0
  155. data/test/test_helper.rb +3 -0
  156. data/website/index.html +271 -0
  157. metadata +304 -0
@@ -0,0 +1,71 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/protocol"
19
+
20
+ require "carps/util"
21
+
22
+ require "carps/mod"
23
+
24
+ require "yaml"
25
+
26
+ require "drb"
27
+
28
+ module CARPS
29
+
30
+ module Sheet
31
+ # A character sheet filled in by a user, sent across the net
32
+ class NewSheet < Message
33
+
34
+ # Extend the protocol
35
+ protoval :character_sheet
36
+
37
+ # Write the sheet
38
+ def initialize sheet
39
+ @sheet = sheet
40
+ end
41
+
42
+ # Parse from the void
43
+ def NewSheet.parse blob
44
+ sheet, blob = find K.character_sheet, blob
45
+ y = nil
46
+ begin
47
+ y = YAML.load sheet
48
+ rescue ArgumentError => e
49
+ end
50
+ if y
51
+ [NewSheet.new(y), blob]
52
+ else
53
+ raise Expected, "Expected valid YAML segment."
54
+ end
55
+ end
56
+
57
+ # Emit
58
+ def emit
59
+ V.character_sheet @sheet.to_yaml
60
+ end
61
+
62
+ # Dump the sheet!
63
+ def dump
64
+ @sheet
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,84 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module CARPS
19
+
20
+ module Sheet
21
+
22
+ # This isn't really the schema, but an object that wraps it
23
+ # and uses it to perform syntactic validations on character sheets
24
+ class Schema
25
+
26
+ # Create a new schema
27
+ def initialize schema
28
+ @schema = schema
29
+ end
30
+
31
+
32
+ # Verify the sheet's syntax.
33
+ #
34
+ # Produce errors if it's invalid, nil if it's valid
35
+ def produce_errors sheet
36
+ errs = []
37
+ @schema.each do |field, type|
38
+ valid, coerced = verify_type sheet[field], type
39
+ if valid
40
+ sheet[field] = coerced
41
+ else
42
+ errs.push field + " was not " + type
43
+ end
44
+ end
45
+ if errs.empty?
46
+ nil
47
+ else
48
+ errs
49
+ end
50
+ end
51
+
52
+ # Create sheet text for the user to edit
53
+ def create_sheet_text user_sheet
54
+ current = {}
55
+ if user_sheet
56
+ current = user_sheet.attributes
57
+ end
58
+
59
+ @schema.each_key do |field|
60
+ unless current.include? field
61
+ current[field] = nil
62
+ end
63
+ end
64
+ sheet = "# Character sheet\n"
65
+ current.each do |field, value|
66
+ type = @schema[field]
67
+ sheet += "# #{field} is #{type}\n"
68
+ sheet += "#{field}: #{value}\n"
69
+ end
70
+ return sheet
71
+ end
72
+
73
+ protected
74
+
75
+ def verify_type val, type_str
76
+ type = TypeParser.parse type_str
77
+ type.verify val
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,161 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "set"
19
+
20
+ module CARPS
21
+
22
+ module Sheet
23
+
24
+ # Types available in character sheets
25
+ #
26
+ # Subclasses must provide a method called valid, which takes a value and determines if it is valid.
27
+ #
28
+ # Subclasses may provide a method called coercion, which should return a symbol referring to a method which coerces a value into a different type (example, :to_s)
29
+ #
30
+ # Subclasses may provide a method called empty which should determine if a value is empty
31
+ class Type
32
+
33
+ def initialize optional
34
+ @optional = optional
35
+ end
36
+
37
+ def verify val
38
+ if val == nil
39
+ if @optional
40
+ return [true, nil]
41
+ end
42
+ end
43
+ ok = false
44
+ if coercion
45
+ ok = valid(val) && val.respond_to?(coercion)
46
+ else
47
+ ok = valid(val)
48
+ end
49
+
50
+ if ok
51
+ if empty(val) and @optional
52
+ return [true, nil]
53
+ else
54
+ coerced = nil
55
+ if coercion
56
+ coerced = val.send coercion
57
+ else
58
+ coerced = val
59
+ end
60
+ [true, coerced]
61
+ end
62
+ else
63
+ [false, nil]
64
+ end
65
+ end
66
+
67
+ # No coercion
68
+ def coercion
69
+ end
70
+
71
+ # Can't be empty
72
+ def empty val
73
+ false
74
+ end
75
+
76
+ end
77
+
78
+ # Accept Fixnums
79
+ class Int < Type
80
+
81
+ def valid val
82
+ val.class == Fixnum
83
+ end
84
+
85
+ end
86
+
87
+ # Accept Strings
88
+ class Text < Type
89
+
90
+ def valid val
91
+ true
92
+ end
93
+
94
+ def coercion
95
+ :to_s
96
+ end
97
+
98
+ def empty val
99
+ if val.class == String
100
+ return val.empty?
101
+ else
102
+ return false
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ # Accept one of a Set of possible values
109
+ class Choice < Type
110
+
111
+ # The second argument is the Set of possible values
112
+ def initialize optional, choices
113
+ super optional
114
+ @choices = choices
115
+ end
116
+
117
+ # Only true for a member of the Set of possible values
118
+ def valid val
119
+ @choices.member? val.downcase
120
+ end
121
+
122
+ end
123
+
124
+ # Accept booleans
125
+ class Bool < Type
126
+
127
+ # Only true for if val.class is TrueClass or FalseClass
128
+ def valid val
129
+ val.class == TrueClass or val.class == FalseClass
130
+ end
131
+
132
+ end
133
+
134
+ # Parse the sheet types from strings
135
+ class TypeParser
136
+ def TypeParser.parse type_name
137
+ type_name.downcase!
138
+ optional_match = type_name.match /^\s*optional\s+((\S+\s+)*?\S+)\s*$/
139
+ optional = false
140
+ if optional_match
141
+ type_name = optional_match[1]
142
+ optional = true
143
+ end
144
+ if type_name == "integer"
145
+ return Int.new optional
146
+ elsif type_name == "text"
147
+ return Text.new optional
148
+ elsif type_name == "boolean"
149
+ return Bool.new optional
150
+ elsif match = type_name.match(/^choice (.+)$/)
151
+ choices = Set.new match[1].split
152
+ return Choice.new optional, choices
153
+ else
154
+ raise StandardError, "Could not parse type name: " + type_name
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+
161
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/ui/question"
19
+
20
+ require "yaml"
21
+
22
+ module CARPS
23
+
24
+ module Sheet
25
+
26
+ # Character sheet semantic verifier that asks the user if the sheet is true
27
+ class UserVerifier
28
+
29
+ # Produce errors if the sheet is incorrect
30
+ def produce_errors sheet
31
+ text = sheet.emit
32
+ puts text
33
+ unless UI::confirm("Is the above character sheet correct?")
34
+ ["User refused to accept sheet."]
35
+ end
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/protocol"
19
+
20
+ module CARPS
21
+
22
+ # Text sent by the server to be viewed on the client.
23
+ class StatusReport < Message
24
+
25
+ # Extend the protocol
26
+ protoval :status_report
27
+
28
+ # Create a status report
29
+ def initialize text
30
+ @text = text
31
+ end
32
+
33
+ # Parse from the void
34
+ def StatusReport.parse blob
35
+ status, blob = find K.status_report, blob
36
+ [StatusReport.new(status), blob]
37
+ end
38
+
39
+ # Emit
40
+ def emit
41
+ V.status_report @text
42
+ end
43
+
44
+ # Display the text
45
+ def display
46
+ puts @text
47
+ end
48
+
49
+ end
50
+
51
+ end
data/lib/carps/mod.rb ADDED
@@ -0,0 +1,40 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/mod/interface"
19
+ require "carps/mod/mod"
20
+ require "carps/mod/dm/interface"
21
+ require "carps/mod/dm/mod"
22
+ require "carps/mod/dm/reporter"
23
+ require "carps/mod/dm/resource"
24
+ require "carps/mod/dm/room"
25
+ require "carps/mod/player/interface"
26
+ require "carps/mod/player/mod"
27
+ require "carps/mod/answers"
28
+ require "carps/mod/client_turn"
29
+ require "carps/mod/dice"
30
+ require "carps/mod/question"
31
+ require "carps/mod/sheet/editor"
32
+ require "carps/mod/sheet/type"
33
+ require "carps/mod/sheet/verifier"
34
+ require "carps/mod/sheet/schema"
35
+ require "carps/mod/sheet/character"
36
+ require "carps/mod/sheet/new_sheet"
37
+ require "carps/mod/status_report"
38
+ require "carps/mod/launch"
39
+ require "carps/mod/rule"
40
+ require "carps/mod/action"
@@ -0,0 +1,104 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # Class containing message keywords. Its name is short :)
19
+ class K
20
+ end
21
+
22
+ # Class containing message keywords which are associated with values.
23
+ class V
24
+ end
25
+
26
+
27
+ # Declare a new protocol keyword which is associated with a value
28
+ def protoval keyword
29
+ # Use the OLD SKOOL for ruby 1.8 support
30
+ K.class_eval <<-"END"
31
+ def K.#{keyword.to_s}
32
+ prefix + "#{keyword.to_s}" + keyword_end
33
+ end
34
+ END
35
+
36
+ V.class_eval <<-"END"
37
+ def V.#{keyword.to_s} data
38
+ prefix + "#{keyword.to_s}" + keyword_end + data + K.end
39
+ end
40
+ END
41
+ end
42
+
43
+ # Declare a new protocol keyword which is a flag or marker
44
+ def protoword keyword
45
+ K.class_eval <<-"END"
46
+ def K.#{keyword.to_s}
47
+ mark_prefix + "#{keyword.to_s}" + keyword_end
48
+ end
49
+ END
50
+ end
51
+
52
+ # End keyword
53
+ protoword "end"
54
+
55
+ module CARPS
56
+
57
+ # CARP protocol keywords associated with values are prefixed by ASCII start of text.
58
+ def prefix
59
+ "\2"
60
+ end
61
+
62
+ # CARP protocol markers are associated with ASCII start of heading
63
+ def mark_prefix
64
+ "\1"
65
+ end
66
+
67
+ # End the prefix, so there are no ambiguities
68
+ def keyword_end
69
+ "\3"
70
+ end
71
+
72
+ class Expected < StandardError
73
+ end
74
+
75
+ module Protocol
76
+
77
+ # Check that the first argument is not nil, if so, raise an 'expected' parse error, using the second argument
78
+ def Protocol.check result, expected
79
+ if result == nil
80
+ raise Expected, expected
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ # Find a field in semi-structured text
87
+ def find field, text
88
+ Protocol::check text, "Expected String for input"
89
+ if field.start_with? mark_prefix
90
+ forget, blob = text.split field, 2
91
+ Protocol::check blob, field
92
+ return ["", blob]
93
+ elsif field.start_with? prefix
94
+ forget, blob = text.split field, 2
95
+ Protocol::check blob, field
96
+ value, blob = blob.split K.end, 2
97
+ Protocol::check value, K.end
98
+ return [value, blob]
99
+ else
100
+ raise StandardError, "Invalid keyword"
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,138 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/protocol/keyword"
19
+
20
+ require "carps/ui/warn"
21
+
22
+ require "drb"
23
+
24
+ require "fileutils"
25
+
26
+ module CARPS
27
+
28
+ # Parse a message from a block of unformatted text
29
+ class MessageParser
30
+
31
+ # Create a new parser from a list of choices
32
+ def initialize choices
33
+ @choices = choices
34
+ end
35
+
36
+ # Parse, choosing from a number of alternative messages, return the first one that suceeds
37
+ def choose_parser blob
38
+ @choices.each do |message|
39
+ begin
40
+ result, text = message.parse blob
41
+ return [result, text]
42
+ rescue Expected
43
+ end
44
+ end
45
+ raise Expected
46
+ end
47
+
48
+ # Parse the text into a message
49
+ def parse text
50
+ input = text
51
+ begin
52
+ msg, blob = choose_parser text
53
+ return msg
54
+ rescue Expected
55
+ UI::warn "An invalid email was received:", input
56
+ return nil
57
+ end
58
+ end
59
+ end
60
+
61
+ # A message
62
+ class Message
63
+
64
+ # Set cryptography information
65
+ def crypt= sig
66
+ @delayed_crypt = sig
67
+ end
68
+
69
+ # Cryptography information
70
+ def crypt
71
+ @delayed_crypt
72
+ end
73
+
74
+ # set who we're from
75
+ def from= addr
76
+ @from = addr
77
+ end
78
+
79
+ # Who we're from
80
+ def from
81
+ @from
82
+ end
83
+
84
+ # Set the session
85
+ def session= session
86
+ @session = session
87
+ end
88
+
89
+ # Get the session
90
+ def session
91
+ @session
92
+ end
93
+
94
+ # Set the path
95
+ def path= path
96
+ @path = path
97
+ end
98
+
99
+ # Save a blob, associated with this mail
100
+ #
101
+ # Only use once. Raises exception if called multiple times.
102
+ def save blob
103
+ if @path
104
+ raise StandardError, "#{self} has already been saved!"
105
+ else
106
+ begin
107
+ @path = write_file_in ".mail/", blob
108
+ rescue StandardError => e
109
+ UI::put_error "Could not save #{self.class} in .mail/:\n#{e.message}"
110
+ end
111
+ end
112
+ @path
113
+ end
114
+
115
+ # Delete the path
116
+ def delete
117
+ if @path
118
+ if File.exists?(@path)
119
+ begin
120
+ FileUtils.rm @path
121
+ rescue StandardError => e
122
+ UI::put_error "Could not delete message: #{e}"
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ # Parse.
129
+ #
130
+ # The first parameter is the email address this text is from
131
+ # The second parameter is the text itself.
132
+ def parse text
133
+ nil
134
+ end
135
+
136
+ end
137
+
138
+ end