Commit 814a7c0930bc36c3de10c13588cb4262042e2884
- Diff rendering mode:
- inline
- side by side
.DS_Store
(1 / 1)
Binary files differ
gpgmime
(10 / 2)
|   | |||
| 39 | 39 | puts infostr | |
| 40 | 40 | end | |
| 41 | 41 | ||
| 42 | result_code = 0 | ||
| 42 | 43 | ||
| 43 | 44 | if ARGV.length < 1 || ARGV.length > 2 | |
| 44 | 45 | help | |
| … | … | ||
| 58 | 58 | ||
| 59 | 59 | if mimeParser.respond_to? :"#{option}" | |
| 60 | 60 | 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 | ||
| 63 | 68 | else | |
| 64 | 69 | $stderr.puts "method #{option} undefined error!" | |
| 65 | 70 | end | |
| 66 | 71 | end | |
| 72 | |||
| 73 | exit result_code | ||
| 67 | 74 | __END__ |
gpgmime.rb
(124 / 38)
|   | |||
| 9 | 9 | require 'digest/sha1' | |
| 10 | 10 | require 'open3' | |
| 11 | 11 | require 'tempfile' | |
| 12 | require "base64" | ||
| 12 | 13 | ||
| 13 | 14 | class MimeParser | |
| 14 | 15 | ||
| … | … | ||
| 138 | 138 | ||
| 139 | 139 | # assigns a value to a given key | |
| 140 | 140 | def setValueForKey( key, value, string = @header_str ) | |
| 141 | if value.strip.length == 0 | ||
| 142 | return | ||
| 143 | end | ||
| 144 | |||
| 141 | 145 | value_range = getKeyValueRange( key, string, ":" ) | |
| 142 | 146 | if value_range != nil | |
| 143 | 147 | string[ *value_range ] = " "+value | |
| … | … | ||
| 173 | 173 | ||
| 174 | 174 | # assigns a value to a given sub key, similar to getValueForSubKey | |
| 175 | 175 | def setValueForSubKey( key, value, string ) | |
| 176 | if value.strip.length == 0 | ||
| 177 | return | ||
| 178 | end | ||
| 179 | |||
| 176 | 180 | keystring = key+"=" | |
| 177 | 181 | /(#{keystring})(.+)(;|#{LINESEP})/mi =~ ( string+";" ) | |
| 178 | 182 | offset = Regexp.last_match.offset(2) | |
| … | … | ||
| 260 | 260 | end | |
| 261 | 261 | ||
| 262 | 262 | ||
| 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("ä", "ä" ). | ||
| 307 | gsub("ö", "ö" ). | ||
| 308 | gsub("ü", "ü" ). | ||
| 309 | gsub("Ä", "Ä"). | ||
| 310 | gsub("Ö", "Ö"). | ||
| 311 | gsub("Ü", "Ü"). | ||
| 312 | gsub("ß", "ß" ). | ||
| 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 | |||
| 263 | 373 | end | |
| 264 | 374 | ||
| 265 | 375 | ||
| … | … | ||
| 432 | 432 | # adds signature information of string to the bottom of | |
| 433 | 433 | # a MIME message | |
| 434 | 434 | 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!("ä", "ä" ) | ||
| 446 | string.gsub!("ö", "ö" ) | ||
| 447 | string.gsub!("ü", "ü" ) | ||
| 448 | string.gsub!("Ä", "Ä") | ||
| 449 | string.gsub!("Ö", "Ö") | ||
| 450 | string.gsub!("Ü", "Ü") | ||
| 451 | string.gsub!("ß", "ß" ) | ||
| 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 ) | ||
| 468 | 436 | end | |
| 469 | 437 | ||
| 470 | 438 | ||
| … | … | ||
| 528 | 528 | optionstr += "s" if passphrase != nil | |
| 529 | 529 | encrypted, gpgmsg, gpg_result_code = | |
| 530 | 530 | gpg( recipient_array, to_encrypt, optionstr, passphrase ) | |
| 531 | |||
| 531 | |||
| 532 | 532 | # handle encrypted result | |
| 533 | 533 | if( gpg_result_code == 0 ) | |
| 534 | 534 | # Success, store encryption result to class internals | |
| … | … | ||
| 567 | 567 | ||
| 568 | 568 | # encrypts class internals or delivers error message in case of errors | |
| 569 | 569 | # 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 ) | ||
| 572 | 572 | end | |
| 573 | 573 | ||
| 574 | 574 | ||
| … | … | ||
| 774 | 774 | ||
| 775 | 775 | # assign original encoding to header | |
| 776 | 776 | 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 ) ) | ||
| 779 | 778 | ||
| 780 | 779 | # exchange content and attach gpg signature info at the end of the message | |
| 781 | 780 | @content_str = content |

