eventmachine 1.0.7-java → 1.0.8-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -82,7 +82,7 @@ static char PrivateMaterials[] = {
82
82
  builtin_passwd_cb
83
83
  *****************/
84
84
 
85
- extern "C" int builtin_passwd_cb (char *buf, int bufsize, int rwflag, void *userdata)
85
+ extern "C" int builtin_passwd_cb (char *buf UNUSED, int bufsize UNUSED, int rwflag UNUSED, void *userdata UNUSED)
86
86
  {
87
87
  strcpy (buf, "kittycat");
88
88
  return 8;
@@ -216,7 +216,7 @@ SslContext_t::~SslContext_t()
216
216
  SslBox_t::SslBox_t
217
217
  ******************/
218
218
 
219
- SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const unsigned long binding):
219
+ SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const uintptr_t binding):
220
220
  bIsServer (is_server),
221
221
  bHandshakeCompleted (false),
222
222
  bVerifyPeer (verify_peer),
@@ -392,7 +392,7 @@ int SslBox_t::PutPlaintext (const char *buf, int bufsize)
392
392
 
393
393
  bool fatal = false;
394
394
  bool did_work = false;
395
- int pending = BIO_pending(pbioWrite);
395
+ int pending = BIO_pending(pbioWrite);
396
396
 
397
397
  while (OutboundQ.HasPages() && pending < SSLBOX_WRITE_BUFFER_SIZE) {
398
398
  const char *page;
@@ -400,7 +400,7 @@ int SslBox_t::PutPlaintext (const char *buf, int bufsize)
400
400
  OutboundQ.Front (&page, &length);
401
401
  assert (page && (length > 0));
402
402
  int n = SSL_write (pSSL, page, length);
403
- pending = BIO_pending(pbioWrite);
403
+ pending = BIO_pending(pbioWrite);
404
404
 
405
405
  if (n > 0) {
406
406
  did_work = true;
@@ -442,9 +442,9 @@ X509 *SslBox_t::GetPeerCert()
442
442
  ssl_verify_wrapper
443
443
  *******************/
444
444
 
445
- extern "C" int ssl_verify_wrapper(int preverify_ok, X509_STORE_CTX *ctx)
445
+ extern "C" int ssl_verify_wrapper(int preverify_ok UNUSED, X509_STORE_CTX *ctx)
446
446
  {
447
- unsigned long binding;
447
+ uintptr_t binding;
448
448
  X509 *cert;
449
449
  SSL *ssl;
450
450
  BUF_MEM *buf;
@@ -453,7 +453,7 @@ extern "C" int ssl_verify_wrapper(int preverify_ok, X509_STORE_CTX *ctx)
453
453
 
454
454
  cert = X509_STORE_CTX_get_current_cert(ctx);
455
455
  ssl = (SSL*) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
456
- binding = (unsigned long) SSL_get_ex_data(ssl, 0);
456
+ binding = (uintptr_t) SSL_get_ex_data(ssl, 0);
457
457
 
458
458
  out = BIO_new(BIO_s_mem());
459
459
  PEM_write_bio_X509(out, cert);
data/ext/ssl.h CHANGED
@@ -61,7 +61,7 @@ class SslBox_t
61
61
  class SslBox_t
62
62
  {
63
63
  public:
64
- SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const unsigned long binding);
64
+ SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const uintptr_t binding);
65
65
  virtual ~SslBox_t();
66
66
 
67
67
  int PutPlaintext (const char*, int);
@@ -38,6 +38,7 @@ module EventMachine
38
38
  super
39
39
  lbp_init_line_state
40
40
  end
41
+
41
42
  def receive_data data
42
43
  if @lbp_mode == :lines
43
44
  begin
@@ -40,7 +40,7 @@ module EventMachine
40
40
  MaxBinaryLength = 32*1024*1024
41
41
 
42
42
  #--
43
- # Will be called recursively until there's no data to read.
43
+ # Will loop internally until there's no data left to read.
44
44
  # That way the user-defined handlers we call can modify the
45
45
  # handling characteristics on a per-token basis.
46
46
  #
@@ -52,45 +52,51 @@ module EventMachine
52
52
  @lt2_delimiter ||= "\n"
53
53
  @lt2_linebuffer ||= []
54
54
 
55
- if @lt2_mode == :lines
56
- if ix = data.index( @lt2_delimiter )
57
- @lt2_linebuffer << data[0...ix]
58
- ln = @lt2_linebuffer.join
59
- @lt2_linebuffer.clear
60
- if @lt2_delimiter == "\n"
61
- ln.chomp!
55
+ remaining_data = data
56
+
57
+ while remaining_data.length > 0
58
+ if @lt2_mode == :lines
59
+ if ix = remaining_data.index( @lt2_delimiter )
60
+ @lt2_linebuffer << remaining_data[0...ix]
61
+ ln = @lt2_linebuffer.join
62
+ @lt2_linebuffer.clear
63
+ if @lt2_delimiter == "\n"
64
+ ln.chomp!
65
+ end
66
+ receive_line ln
67
+ remaining_data = remaining_data[(ix+@lt2_delimiter.length)..-1]
68
+ else
69
+ @lt2_linebuffer << remaining_data
70
+ remaining_data = ""
62
71
  end
63
- receive_line ln
64
- receive_data data[(ix+@lt2_delimiter.length)..-1]
65
- else
66
- @lt2_linebuffer << data
67
- end
68
- elsif @lt2_mode == :text
69
- if @lt2_textsize
70
- needed = @lt2_textsize - @lt2_textpos
71
- will_take = if data.length > needed
72
- needed
73
- else
74
- data.length
75
- end
76
-
77
- @lt2_textbuffer << data[0...will_take]
78
- tail = data[will_take..-1]
79
-
80
- @lt2_textpos += will_take
81
- if @lt2_textpos >= @lt2_textsize
82
- # Reset line mode (the default behavior) BEFORE calling the
83
- # receive_binary_data. This makes it possible for user code
84
- # to call set_text_mode, enabling chains of text blocks
85
- # (which can possibly be of different sizes).
86
- set_line_mode
87
- receive_binary_data @lt2_textbuffer.join
88
- receive_end_of_binary_data
72
+ elsif @lt2_mode == :text
73
+ if @lt2_textsize
74
+ needed = @lt2_textsize - @lt2_textpos
75
+ will_take = if remaining_data.length > needed
76
+ needed
77
+ else
78
+ remaining_data.length
79
+ end
80
+
81
+ @lt2_textbuffer << remaining_data[0...will_take]
82
+ tail = remaining_data[will_take..-1]
83
+
84
+ @lt2_textpos += will_take
85
+ if @lt2_textpos >= @lt2_textsize
86
+ # Reset line mode (the default behavior) BEFORE calling the
87
+ # receive_binary_data. This makes it possible for user code
88
+ # to call set_text_mode, enabling chains of text blocks
89
+ # (which can possibly be of different sizes).
90
+ set_line_mode
91
+ receive_binary_data @lt2_textbuffer.join
92
+ receive_end_of_binary_data
93
+ end
94
+
95
+ remaining_data = tail
96
+ else
97
+ receive_binary_data remaining_data
98
+ remaining_data = ""
89
99
  end
90
-
91
- receive_data tail
92
- else
93
- receive_binary_data data
94
100
  end
95
101
  end
96
102
  end
@@ -48,20 +48,20 @@ module EventMachine
48
48
  # puts 'Email failed!'
49
49
  # }
50
50
  #
51
- # Sending generated emails (using mailfactory)
51
+ # Sending generated emails (using Mail)
52
52
  #
53
- # mail = MailFactory.new
54
- # mail.to = 'someone@site.co'
55
- # mail.from = 'me@site.com'
56
- # mail.subject = 'hi!'
57
- # mail.text = 'hello world'
58
- # mail.html = '<h1>hello world</h1>'
53
+ # mail = Mail.new do
54
+ # from 'alice@example.com'
55
+ # to 'bob@example.com'
56
+ # subject 'This is a test email'
57
+ # body 'Hello, world!'
58
+ # end
59
59
  #
60
60
  # email = EM::P::SmtpClient.send(
61
- # :domain=>'site.com',
62
- # :from=>mail.from,
61
+ # :domain=>'example.com',
62
+ # :from=>mail.from.first,
63
63
  # :to=>mail.to,
64
- # :content=>"#{mail.to_s}\r\n.\r\n"
64
+ # :message=>mail.to_s
65
65
  # )
66
66
  #
67
67
  class SmtpClient < Connection
@@ -108,25 +108,29 @@ module EventMachine
108
108
  # of each requested recipient is available after the call completes. TODO, we should define
109
109
  # an overridable stub that will be called on rejection of a recipient or a sender, giving
110
110
  # user code the chance to try again or abort the connection.
111
- # :header => Required hash of values to be transmitted in the header of the message.
112
- # The hash keys are the names of the headers (do NOT append a trailing colon), and the values are strings
113
- # containing the header values. TODO, support Arrays of header values, which would cause us to
114
- # send that specific header line more than once.
111
+ #
112
+ # One of either :message, :content, or :header and :body is required:
113
+ #
114
+ # :message => String
115
+ # A valid RFC2822 Internet Message.
116
+ # :content => String
117
+ # Raw data which MUST be in correct SMTP body format, with escaped leading dots and a trailing
118
+ # dot line.
119
+ # :header => String or Hash of values to be transmitted in the header of the message.
120
+ # The hash keys are the names of the headers (do NOT append a trailing colon), and the values
121
+ # are strings containing the header values. TODO, support Arrays of header values, which would
122
+ # cause us to send that specific header line more than once.
115
123
  #
116
124
  # @example
117
125
  # :header => {"Subject" => "Bogus", "CC" => "myboss@example.com"}
118
126
  #
119
- # :body => Optional string, defaults blank.
127
+ # :body => Optional String or Array of Strings, defaults blank.
120
128
  # This will be passed as the body of the email message.
121
129
  # TODO, this needs to be significantly beefed up. As currently written, this requires the caller
122
130
  # to properly format the input into CRLF-delimited lines of 7-bit characters in the standard
123
131
  # SMTP transmission format. We need to be able to automatically convert binary data, and add
124
- # correct line-breaks to text data. I think the :body parameter should remain as it is, and we
125
- # should add a :content parameter that contains autoconversions and/or conversion parameters.
126
- # Then we can check if either :body or :content is present and do the right thing.
127
- # :content => Optional array or string
128
- # Alternative to providing header and body, an array or string of raw data which MUST be in
129
- # correct SMTP body format, including a trailing dot line
132
+ # correct line-breaks to text data.
133
+ #
130
134
  # :verbose => Optional.
131
135
  # If true, will cause a lot of information (including the server-side of the
132
136
  # conversation) to be dumped to $>.
@@ -233,12 +237,15 @@ module EventMachine
233
237
  close_connection_after_writing
234
238
  end
235
239
 
240
+ def send_ehlo
241
+ send_data "EHLO #{@args[:domain]}\r\n"
242
+ end
243
+
236
244
  def receive_signon
237
245
  return invoke_error unless @range == 2
238
- send_data "EHLO #{@args[:domain]}\r\n"
246
+ send_ehlo
239
247
  @responder = :receive_ehlo_response
240
248
  end
241
-
242
249
  def receive_ehlo_response
243
250
  return invoke_error unless @range == 2
244
251
  @server_caps = @msg
@@ -258,6 +265,15 @@ module EventMachine
258
265
  def receive_starttls_response
259
266
  return invoke_error unless @range == 2
260
267
  start_tls
268
+ invoke_ehlo_over_tls
269
+ end
270
+
271
+ def invoke_ehlo_over_tls
272
+ send_ehlo
273
+ @responder = :receive_ehlo_over_tls_response
274
+ end
275
+ def receive_ehlo_over_tls_response
276
+ return invoke_error unless @range == 2
261
277
  invoke_auth
262
278
  end
263
279
 
@@ -316,6 +332,10 @@ module EventMachine
316
332
  invoke_rcpt_to
317
333
  end
318
334
 
335
+ def escape_leading_dots(s)
336
+ s.gsub(/^\./, '..')
337
+ end
338
+
319
339
  def invoke_data
320
340
  send_data "DATA\r\n"
321
341
  @responder = :receive_data_response
@@ -323,25 +343,34 @@ module EventMachine
323
343
  def receive_data_response
324
344
  return invoke_error unless @range == 3
325
345
 
326
- # The data to send can be given either in @args[:content] (an array or string of raw data
327
- # which MUST be in correct SMTP body format, including a trailing dot line), or a header and
328
- # body given in @args[:header] and @args[:body].
346
+ # The data to send can be given in either @args[:message], @args[:content], or the
347
+ # combination of @args[:header] and @args[:body].
348
+ #
349
+ # - @args[:message] (String) MUST be a valid RFC2822 Internet Message
329
350
  #
330
- if @args[:content]
351
+ # - @args[:content] (String) MUST be in correct SMTP body format, with escaped
352
+ # leading dots and a trailing dot line
353
+ #
354
+ # - @args[:header] (Hash or String)
355
+ # - @args[:body] (Array or String)
356
+ if @args[:message]
357
+ send_data escape_leading_dots(@args[:message].to_s)
358
+ send_data "\r\n.\r\n"
359
+ elsif @args[:content]
331
360
  send_data @args[:content].to_s
332
361
  else
333
362
  # The header can be a hash or an array.
334
363
  if @args[:header].is_a?(Hash)
335
- (@args[:header] || {}).each {|k,v| send_data "#{k}: #{v}\r\n" }
364
+ (@args[:header] || {}).each {|k,v| send_data escape_leading_dots("#{k}: #{v}\r\n") }
336
365
  else
337
- send_data @args[:header].to_s
366
+ send_data escape_leading_dots(@args[:header].to_s)
338
367
  end
339
368
  send_data "\r\n"
340
369
 
341
370
  if @args[:body].is_a?(Array)
342
- @args[:body].each {|e| send_data e}
371
+ @args[:body].each {|e| send_data escape_leading_dots(e)}
343
372
  else
344
- send_data @args[:body].to_s
373
+ send_data escape_leading_dots(@args[:body].to_s)
345
374
  end
346
375
 
347
376
  send_data "\r\n.\r\n"
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "1.0.7"
2
+ VERSION = "1.0.8"
3
3
  end
@@ -184,7 +184,15 @@ module EventMachine
184
184
  add_timer(0) { signal_loopbreak }
185
185
  end
186
186
  @reactor_thread = Thread.current
187
- run_machine
187
+
188
+ # Rubinius needs to come back into "Ruby space" for GC to work,
189
+ # so we'll crank the machine here.
190
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
191
+ while run_machine_once; end
192
+ else
193
+ run_machine
194
+ end
195
+
188
196
  ensure
189
197
  until @tails.empty?
190
198
  @tails.pop.call
@@ -26,6 +26,26 @@ class TestLineText2 < Test::Unit::TestCase
26
26
  assert_equal( ["Line 1", "Line 2", "Line 3"], a.lines )
27
27
  end
28
28
 
29
+ # The basic test above shows that extra newlines are chomped
30
+ # This test shows that newlines are preserved if the delimiter isn't \n
31
+ class PreserveNewlines
32
+ include EM::Protocols::LineText2
33
+ attr_reader :lines
34
+ def initialize *args
35
+ super
36
+ @delim = "|"
37
+ set_delimiter @delim
38
+ end
39
+ def receive_line line
40
+ (@lines ||= []) << line
41
+ end
42
+ end
43
+ def test_preserve_newlines
44
+ a = PreserveNewlines.new
45
+ a.receive_data "aaa|bbb|ccc|\n|\r\n| \t ||"
46
+ assert_equal( ["aaa", "bbb", "ccc", "\n", "\r\n", " \t ", ""], a.lines )
47
+ end
48
+
29
49
  class ChangeDelimiter
30
50
  include EM::Protocols::LineText2
31
51
  attr_reader :lines
@@ -52,4 +52,24 @@ class TestSmtpClient < Test::Unit::TestCase
52
52
  assert(err)
53
53
  end
54
54
 
55
+
56
+ EM::Protocols::SmtpClient.__send__(:public, :escape_leading_dots)
57
+
58
+ def test_escaping
59
+ smtp = EM::Protocols::SmtpClient.new :domain => "example.com"
60
+
61
+ expectations = {
62
+ "Hello\r\n" => "Hello\r\n",
63
+ "\r\n.whatever\r\n" => "\r\n..whatever\r\n",
64
+ "\r\n.\r\n" => "\r\n..\r\n",
65
+ "\r\n.\r\n." => "\r\n..\r\n..",
66
+ ".\r\n.\r\n" => "..\r\n..\r\n",
67
+ "..\r\n" => "...\r\n"
68
+ }
69
+
70
+ expectations.each do |input, output|
71
+ assert_equal output, smtp.escape_leading_dots(input)
72
+ end
73
+ end
74
+
55
75
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventmachine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: java
6
6
  authors:
7
7
  - Francis Cianfrocca
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-02-10 00:00:00.000000000 Z
12
+ date: 2015-08-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
@@ -192,6 +192,7 @@ files:
192
192
  - lib/em/version.rb
193
193
  - lib/eventmachine.rb
194
194
  - lib/jeventmachine.rb
195
+ - lib/rubyeventmachine.jar
195
196
  - rakelib/cpp.rake_example
196
197
  - rakelib/package.rake
197
198
  - rakelib/test.rake
@@ -254,7 +255,6 @@ files:
254
255
  - tests/test_timers.rb
255
256
  - tests/test_ud.rb
256
257
  - tests/test_unbind_reason.rb
257
- - lib/rubyeventmachine.jar
258
258
  homepage: http://rubyeventmachine.com
259
259
  licenses:
260
260
  - Ruby
@@ -284,7 +284,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
284
  version: '0'
285
285
  requirements: []
286
286
  rubyforge_project: eventmachine
287
- rubygems_version: 2.1.9
287
+ rubygems_version: 2.4.8
288
288
  signing_key:
289
289
  specification_version: 4
290
290
  summary: Ruby/EventMachine library