Commit 814a7c0930bc36c3de10c13588cb4262042e2884

  • avatar
  • ol42
  • Wed Oct 14 23:33:16 CEST 2009
added base64 support for gpg signature insertion
.DS_Store
(1 / 1)
Binary files differ
gpgmime
(10 / 2)
  
3939 puts infostr
4040end
4141
42result_code = 0
4243
4344if ARGV.length < 1 || ARGV.length > 2
4445 help
5858
5959 if mimeParser.respond_to? :"#{option}"
6060 mimeParser.read_next_message( $stdin )
61 mimeParser.send( :"#{option}", passphrase )
62 puts mimeParser.getMessage
61 gpg_error_msg = mimeParser.send( :"#{option}", passphrase )
62 if gpg_error_msg.length == 0
63 puts mimeParser.getMessage
64 else
65 STDERR.puts gpg_error_msg
66 result_code = -1
67 end
6368 else
6469 $stderr.puts "method #{option} undefined error!"
6570 end
6671end
72
73exit result_code
6774__END__
gpgmime.rb
(124 / 38)
  
99require 'digest/sha1'
1010require 'open3'
1111require 'tempfile'
12require "base64"
1213
1314class MimeParser
1415
138138
139139 # assigns a value to a given key
140140 def setValueForKey( key, value, string = @header_str )
141 if value.strip.length == 0
142 return
143 end
144
141145 value_range = getKeyValueRange( key, string, ":" )
142146 if value_range != nil
143147 string[ *value_range ] = " "+value
173173
174174 # assigns a value to a given sub key, similar to getValueForSubKey
175175 def setValueForSubKey( key, value, string )
176 if value.strip.length == 0
177 return
178 end
179
176180 keystring = key+"="
177181 /(#{keystring})(.+)(;|#{LINESEP})/mi =~ ( string+";" )
178182 offset = Regexp.last_match.offset(2)
260260 end
261261
262262
263 # returns the boundary string
264 def getBoundary()
265 cntType = getContentType()
266 boundary = getValueForSubKey( "boundary", cntType )
267
268 if boundary == nil || boundary == ""
269 return nil # no boundaries
270 else
271 "--"+boundary.gsub("\"","").strip
272 end
273
274 end
275
276
277 # returns all array with ranges for all sections
278 # or main content section if no boundaries are defined
279 def getSectionRangeArray()
280 # get boundary
281 boundary = getBoundary()
282 if boundary == nil
283 return [ (0..getContent.length) ] # no boundaries, return main section
284 end
285
286 next_start_idx = 0
287 range_array = [ (next_start_idx..next_start_idx) ]
288
289 content = getContent
290 while /^#{boundary}(\r\n|\n|--)/ =~ content[next_start_idx..content.length]
291 next_start_idx = next_start_idx + Regexp.last_match.offset(1)[1]
292 length = Regexp.last_match.offset(0)[0]
293
294 range_array[-1] = (range_array[-1].min ... range_array[-1].min + length)
295 range_array << (next_start_idx .. next_start_idx)
296 end
297
298 range_array[1...-1]
299 end
300
301
302 # adds a footer text to each section
303 def add_footer_to_each_section( footer_text)
304
305 footer_html_text = footer_text.
306 gsub("ä", "&auml;" ).
307 gsub("ö", "&ouml;" ).
308 gsub("ü", "&uuml;" ).
309 gsub("Ä", "&Auml;").
310 gsub("Ö", "&Ouml;").
311 gsub("Ü", "&Uuml;").
312 gsub("ß", "&szlig;" ).
313 gsub("\n", "<br>\n")
314
315 footer_7bit_text = footer_text.
316 gsub("ä", "ae" ).
317 gsub("ö", "oe" ).
318 gsub("ü", "ue" ).
319 gsub("Ä", "Ae").
320 gsub("Ö", "OE").
321 gsub("Ü", "UE").
322 gsub("ß", "ss" )
323
324 newContent = ""
325 boundary = getBoundary()
326 boundary = "" if !boundary
327
328 rangeArray = getSectionRangeArray
329 rangeArray.each do |secrange|
330
331 # for each MIME section extract header and content
332 section = @content_str[secrange]
333 /^\r\n|\n$/ =~ section
334 header = section[ 0 .. Regexp.last_match.begin(0) - $~.length ]
335 content = section[ Regexp.last_match.offset(0)[1]..section.length ]
336 isBase64 = getValueForKey( "Content-Transfer-Encoding", header ).match(/base64/i)
337 is7Bit = getValueForKey( "Content-Transfer-Encoding", header ).match(/7bit/i)
338 isUTF8 = getValueForKey( "Content-Type", header ).match(/utf-8/i)
339 isTextHtml = getValueForKey( "Content-Type", header ).match(/text\/html/i)
340 isTextPlain = getValueForKey( "Content-Type", header ).match(/text\/plain/i)
341
342 # decode content if it is base64
343 content = Base64.decode64(content) if isBase64
344
345 # add footer message
346 if isTextHtml
347 # add footer for html
348 if( content.match(/<\/body>/) )
349 content.sub!("</body>", "<hr/>" + footer_html_text + "<hr/></body>")
350 else
351 content << "<hr/>" + footer_html_text + "<hr/>\r\n"
352 end
353
354 else isTextPlain
355 # add footer for plain text
356 content << "\r\n" +
357 "________________________________________________________________________________\n" +
358 ( if !isUTF8 then footer_7bit_text else footer_text end ) + "\r\n"
359 end
360
361 # encode to bas64 again if it was encoded
362 content = Base64.encode64(content) if isBase64
363
364 # and add section to new composed message
365 newContent << boundary + "\r\n" + header + "\r\n" + content
366
367 end # rangeArray.each do
368
369 newContent << boundary + "--\r\n" if rangeArray.length > 1
370 @content_str = newContent
371 end
372
263373end
264374
265375
432432 # adds signature information of string to the bottom of
433433 # a MIME message
434434 def add_signature( string )
435 is_html = false
436
437 # check mime type and get boundary
438 cntType = getContentType()
439 if cntType == nil
440 return "no content type error!"
441 end
442
443 # depending on format we patch html or insert plain text
444 if cntType.downcase.match("multipart/alternative") or cntType.downcase.match("text/html")
445 string.gsub!("ä", "&auml;" )
446 string.gsub!("ö", "&ouml;" )
447 string.gsub!("ü", "&uuml;" )
448 string.gsub!("Ä", "&Auml;")
449 string.gsub!("Ö", "&Ouml;")
450 string.gsub!("Ü", "&Uuml;")
451 string.gsub!("ß", "&szlig;" )
452
453 @content_str.sub!("</body>", "<hr/>" + string.gsub("\n", "<br>\n") + "<hr/></body>")
454 else
455 string.gsub!("ä", "ae" )
456 string.gsub!("ö", "oe" )
457 string.gsub!("ü", "ue" )
458 string.gsub!("Ä", "Ae")
459 string.gsub!("Ö", "Oe")
460 string.gsub!("Ü", "Ue")
461 string.gsub!("ß", "ss" )
462
463 @content_str << LINESEP +
464 "________________________________________________________________________________\n" +
465 string
466 end
467
435 add_footer_to_each_section( string )
468436 end
469437
470438
528528 optionstr += "s" if passphrase != nil
529529 encrypted, gpgmsg, gpg_result_code =
530530 gpg( recipient_array, to_encrypt, optionstr, passphrase )
531
531
532532 # handle encrypted result
533533 if( gpg_result_code == 0 )
534534 # Success, store encryption result to class internals
567567
568568 # encrypts class internals or delivers error message in case of errors
569569 # if passphrase is provided, the message is signed with the default key
570 def encrypt
571 encrypt_and_sign( nil )
570 def encrypt( passphrase = nil, recipient_array = nil )
571 encrypt_and_sign( nil, recipient_array )
572572 end
573573
574574
774774
775775 # assign original encoding to header
776776 setContentType( getValueForKey( "Content-Type", header ) )
777 orig_encoding = getValueForKey( "Content-Transfer-Encoding", header )
778 setContentTransferEncoding( orig_encoding ) if orig_encoding.length > 0
777 setContentTransferEncoding( getValueForKey( "Content-Transfer-Encoding", header ) )
779778
780779 # exchange content and attach gpg signature info at the end of the message
781780 @content_str = content