eventmachine 1.0.7-java → 1.0.8-java

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.
@@ -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