sisimai 5.3.0-java → 5.4.0-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.
- checksums.yaml +4 -4
- data/ChangeLog.md +12 -0
- data/Makefile +3 -2
- data/README-JA.md +2 -2
- data/README.md +6 -6
- data/lib/sisimai/address.rb +45 -56
- data/lib/sisimai/arf.rb +11 -16
- data/lib/sisimai/datetime.rb +16 -50
- data/lib/sisimai/fact/json.rb +5 -5
- data/lib/sisimai/fact/yaml.rb +3 -3
- data/lib/sisimai/fact.rb +11 -12
- data/lib/sisimai/lda.rb +3 -3
- data/lib/sisimai/lhost/activehunter.rb +4 -6
- data/lib/sisimai/lhost/amazonses.rb +5 -6
- data/lib/sisimai/lhost/apachejames.rb +7 -9
- data/lib/sisimai/lhost/biglobe.rb +3 -5
- data/lib/sisimai/lhost/courier.rb +4 -6
- data/lib/sisimai/lhost/domino.rb +4 -5
- data/lib/sisimai/lhost/dragonfly.rb +3 -5
- data/lib/sisimai/lhost/einsundeins.rb +6 -8
- data/lib/sisimai/lhost/exchange2003.rb +10 -12
- data/lib/sisimai/lhost/exchange2007.rb +4 -5
- data/lib/sisimai/lhost/exim.rb +6 -8
- data/lib/sisimai/lhost/ezweb.rb +10 -12
- data/lib/sisimai/lhost/fml.rb +2 -3
- data/lib/sisimai/lhost/gmail.rb +4 -6
- data/lib/sisimai/lhost/gmx.rb +6 -8
- data/lib/sisimai/lhost/googlegroups.rb +1 -2
- data/lib/sisimai/lhost/googleworkspace.rb +3 -4
- data/lib/sisimai/lhost/imailserver.rb +6 -7
- data/lib/sisimai/lhost/interscanmss.rb +1 -2
- data/lib/sisimai/lhost/kddi.rb +5 -8
- data/lib/sisimai/lhost/mailfoundry.rb +4 -7
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +4 -6
- data/lib/sisimai/lhost/messagingserver.rb +5 -7
- data/lib/sisimai/lhost/mfilter.rb +4 -6
- data/lib/sisimai/lhost/notes.rb +7 -9
- data/lib/sisimai/lhost/opensmtpd.rb +2 -4
- data/lib/sisimai/lhost/postfix.rb +8 -11
- data/lib/sisimai/lhost/qmail.rb +5 -8
- data/lib/sisimai/lhost/sendmail.rb +7 -10
- data/lib/sisimai/lhost/v5sendmail.rb +15 -17
- data/lib/sisimai/lhost/verizon.rb +9 -14
- data/lib/sisimai/lhost/x1.rb +4 -6
- data/lib/sisimai/lhost/x2.rb +5 -7
- data/lib/sisimai/lhost/x3.rb +3 -4
- data/lib/sisimai/lhost/x6.rb +4 -6
- data/lib/sisimai/lhost/zoho.rb +6 -8
- data/lib/sisimai/lhost.rb +1 -1
- data/lib/sisimai/mail/mbox.rb +1 -1
- data/lib/sisimai/mail/memory.rb +1 -1
- data/lib/sisimai/mail.rb +8 -8
- data/lib/sisimai/message.rb +11 -13
- data/lib/sisimai/reason/authfailure.rb +10 -10
- data/lib/sisimai/reason/badreputation.rb +4 -6
- data/lib/sisimai/reason/blocked.rb +6 -8
- data/lib/sisimai/reason/contenterror.rb +5 -6
- data/lib/sisimai/reason/delivered.rb +2 -2
- data/lib/sisimai/reason/exceedlimit.rb +7 -8
- data/lib/sisimai/reason/expired.rb +6 -7
- data/lib/sisimai/reason/failedstarttls.rb +5 -7
- data/lib/sisimai/reason/feedback.rb +2 -2
- data/lib/sisimai/reason/filtered.rb +7 -10
- data/lib/sisimai/reason/hasmoved.rb +4 -5
- data/lib/sisimai/reason/hostunknown.rb +6 -7
- data/lib/sisimai/reason/mailboxfull.rb +7 -8
- data/lib/sisimai/reason/mailererror.rb +5 -8
- data/lib/sisimai/reason/mesgtoobig.rb +5 -6
- data/lib/sisimai/reason/networkerror.rb +5 -8
- data/lib/sisimai/reason/norelaying.rb +4 -5
- data/lib/sisimai/reason/notaccept.rb +5 -8
- data/lib/sisimai/reason/notcompliantrfc.rb +5 -6
- data/lib/sisimai/reason/onhold.rb +6 -9
- data/lib/sisimai/reason/policyviolation.rb +6 -9
- data/lib/sisimai/reason/rejected.rb +5 -6
- data/lib/sisimai/reason/requireptr.rb +6 -7
- data/lib/sisimai/reason/securityerror.rb +6 -9
- data/lib/sisimai/reason/spamdetected.rb +8 -9
- data/lib/sisimai/reason/speeding.rb +6 -7
- data/lib/sisimai/reason/suppressed.rb +3 -7
- data/lib/sisimai/reason/suspend.rb +5 -7
- data/lib/sisimai/reason/syntaxerror.rb +3 -5
- data/lib/sisimai/reason/systemerror.rb +6 -9
- data/lib/sisimai/reason/systemfull.rb +5 -8
- data/lib/sisimai/reason/toomanyconn.rb +5 -6
- data/lib/sisimai/reason/undefined.rb +2 -2
- data/lib/sisimai/reason/userunknown.rb +8 -9
- data/lib/sisimai/reason/vacation.rb +4 -5
- data/lib/sisimai/reason/virusdetected.rb +4 -5
- data/lib/sisimai/reason.rb +13 -13
- data/lib/sisimai/rfc1123.rb +4 -8
- data/lib/sisimai/rfc1894.rb +5 -6
- data/lib/sisimai/rfc2045.rb +27 -31
- data/lib/sisimai/rfc3464/thirdparty.rb +1 -1
- data/lib/sisimai/rfc3464.rb +7 -9
- data/lib/sisimai/rfc3834.rb +5 -9
- data/lib/sisimai/rfc5322.rb +8 -26
- data/lib/sisimai/rfc791.rb +6 -4
- data/lib/sisimai/rhost/google.rb +8 -0
- data/lib/sisimai/rhost/microsoft.rb +17 -5
- data/lib/sisimai/rhost.rb +2 -2
- data/lib/sisimai/smtp/command.rb +1 -1
- data/lib/sisimai/smtp/failure.rb +5 -12
- data/lib/sisimai/smtp/reply.rb +3 -5
- data/lib/sisimai/smtp/status.rb +14 -24
- data/lib/sisimai/smtp/transcript.rb +1 -10
- data/lib/sisimai/string.rb +20 -30
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +11 -11
- data/set-of-emails/maildir/bsd/rhost-microsoft-06.eml +45 -0
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 6e7c01c8568c5c1922dc71d9948d86eb8684bf18a981243b3e476a2de4d187f6
         | 
| 4 | 
            +
              data.tar.gz: 0ca7b2415f6afc00b98f9e8e25b939f9962d0aba7c08f0c1689647a26f6329ec
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 201468479dbd8c7cf75d6ac3d7560e2ec9bf9badb6d9a847c5979264138477699450a15a9553e1e919f69dd8f369c9792af6fac56e2a07eea5940daa4a943273
         | 
| 7 | 
            +
              data.tar.gz: 933f217ffb3bc6092e2f338a4df40291e11ad3c59b6bdb22e56ba53d9b88368ff21ab37687d2dc87873f3ce4327aede14913616312eff1ee716768a7c960b816
         | 
    
        data/ChangeLog.md
    CHANGED
    
    | @@ -3,6 +3,18 @@ RELEASE NOTES for Ruby version of Sisimai | |
| 3 3 | 
             
            - releases: "https://github.com/sisimai/rb-sisimai/releases"
         | 
| 4 4 | 
             
            - download: "https://rubygems.org/gems/sisimai"
         | 
| 5 5 |  | 
| 6 | 
            +
            v5.4.0
         | 
| 7 | 
            +
            ---------------------------------------------------------------------------------------------------
         | 
| 8 | 
            +
            - release: "Tue,  1 Jul 2025 20:22:22 +0900 (JST)"
         | 
| 9 | 
            +
            - version: "5.4.0"
         | 
| 10 | 
            +
            - changes:
         | 
| 11 | 
            +
              - #341 #342 #345 Implement the new status code `5.7.515` as `authfailure` and other undocumented
         | 
| 12 | 
            +
                status codes begin with `4.4.` as `systemerror` of Microsoft in `Sisimai::Rhost::Microsoft`.
         | 
| 13 | 
            +
              - #343 #346 Some internal methods do not return `nil`, standardize return values to align with
         | 
| 14 | 
            +
                zero-value principle.
         | 
| 15 | 
            +
              - #347 Support a frozen string literal
         | 
| 16 | 
            +
              - #349 #350 Implement new status codes of Google: `4.7.40` and `5.7.32` as `authfailure`.
         | 
| 17 | 
            +
             | 
| 6 18 | 
             
            v5.3.0
         | 
| 7 19 | 
             
            ---------------------------------------------------------------------------------------------------
         | 
| 8 20 | 
             
            - release: "Sat, 29 Mar 2025 06:04:41 +0900 (JST)"
         | 
    
        data/Makefile
    CHANGED
    
    | @@ -16,6 +16,7 @@ CP    := cp | |
| 16 16 | 
             
            RM    := rm -f
         | 
| 17 17 |  | 
| 18 18 | 
             
            DEPENDENCIES  = bundle rake minitest
         | 
| 19 | 
            +
            RUBYARGUMENT  = --enable-frozen-string-literal
         | 
| 19 20 | 
             
            .DEFAULT_GOAL = git-status
         | 
| 20 21 | 
             
            REPOS_TARGETS = git-status git-push git-commit-amend git-tag-list git-diff git-reset-soft \
         | 
| 21 22 | 
             
            				git-rm-cached git-branch
         | 
| @@ -58,11 +59,11 @@ release: | |
| 58 59 | 
             
            test: user-test author-test
         | 
| 59 60 | 
             
            user-test:
         | 
| 60 61 | 
             
            	# Suppress warning messages until v5.5.0
         | 
| 61 | 
            -
            	rake publictest 2> /dev/null
         | 
| 62 | 
            +
            	RUBYOPT="$(RUBYARGUMENT)" rake publictest 2> /dev/null
         | 
| 62 63 |  | 
| 63 64 | 
             
            author-test:
         | 
| 64 65 | 
             
            	# Suppress warning messages until v5.5.0
         | 
| 65 | 
            -
            	rake privatetest 2> /dev/null
         | 
| 66 | 
            +
            	RUBYOPT="$(RUBYARGUMENT)" rake privatetest 2> /dev/null
         | 
| 66 67 |  | 
| 67 68 | 
             
            check:
         | 
| 68 69 | 
             
            	find lib -type f -exec grep --color -E ' $$' {} /dev/null \;
         | 
    
        data/README-JA.md
    CHANGED
    
    | @@ -23,7 +23,7 @@ | |
| 23 23 | 
             
            > SisimaiはPerlモジュールまたはRuby Gemですが、PHPやPython、GoやRustなどJSONを読める言語であれば
         | 
| 24 24 | 
             
            > どのような環境においても解析結果を得ることでバウンスの発生状況を捉えるのにとても有用です。
         | 
| 25 25 |  | 
| 26 | 
            -
            - [**README( | 
| 26 | 
            +
            - [**README(🇬🇧)**](README.md)
         | 
| 27 27 | 
             
            - [シシマイ? | What is Sisimai](#what-is-sisimai)
         | 
| 28 28 | 
             
                - [主な特徴的機能 | The key features](#the-key-features-of-sisimai)
         | 
| 29 29 | 
             
                - [コマンドラインでのデモ | Command line demo](#command-line-demo)
         | 
| @@ -447,7 +447,7 @@ Related sites | |
| 447 447 |  | 
| 448 448 | 
             
            See also
         | 
| 449 449 | 
             
            ---------------------------------------------------------------------------------------------------
         | 
| 450 | 
            -
            * [README.md - README.md in English](https://github.com/sisimai/rb-sisimai/blob/master/README.md)
         | 
| 450 | 
            +
            * [README.md - README.md in English(🇬🇧)](https://github.com/sisimai/rb-sisimai/blob/master/README.md)
         | 
| 451 451 | 
             
            * [RFC3463 - Enhanced Mail System Status Codes](https://tools.ietf.org/html/rfc3463)
         | 
| 452 452 | 
             
            * [RFC3464 - An Extensible Message Format for Delivery Status Notifications](https://tools.ietf.org/html/rfc3464)
         | 
| 453 453 | 
             
            * [RFC3834 - Recommendations for Automatic Responses to Electronic Mail](https://tools.ietf.org/html/rfc3834)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -25,7 +25,7 @@ | |
| 25 25 | 
             
            > such as PHP, Python, Go, and Rust. By obtaining the analysis results, it is very useful for understanding
         | 
| 26 26 | 
             
            > the bounce occurrence status. 
         | 
| 27 27 |  | 
| 28 | 
            -
            - [**README-JA( | 
| 28 | 
            +
            - [**README-JA(🇯🇵)**](README-JA.md)
         | 
| 29 29 | 
             
            - [What is Sisimai](#what-is-sisimai)
         | 
| 30 30 | 
             
                - [The key features of sisimai](#the-key-features-of-sisimai)
         | 
| 31 31 | 
             
                - [Command line demo](#command-line-demo)
         | 
| @@ -57,10 +57,10 @@ | |
| 57 57 |  | 
| 58 58 | 
             
            What is Sisimai
         | 
| 59 59 | 
             
            ===================================================================================================
         | 
| 60 | 
            -
            Sisimai is a library that decodes complex and diverse bounce emails and | 
| 61 | 
            -
            delivery failure, such as the reason for the bounce and the recipient | 
| 62 | 
            -
            data. It is also possible to output in JSON format. The Ruby version | 
| 63 | 
            -
            Perl version of Sisimai | 
| 60 | 
            +
            Sisimai (pronounced /ɕi.ɕi.ma.i/) is a library that decodes complex and diverse bounce emails and
         | 
| 61 | 
            +
            outputs the results of the delivery failure, such as the reason for the bounce and the recipient
         | 
| 62 | 
            +
            email address, in structured data. It is also possible to output in JSON format. The Ruby version
         | 
| 63 | 
            +
            of Sisimai is ported from [the Perl version of Sisimai](https://github.com/sisimai/p5-sisimai/).
         | 
| 64 64 |  | 
| 65 65 | 
             
            
         | 
| 66 66 |  | 
| @@ -450,7 +450,7 @@ Related Sites | |
| 450 450 |  | 
| 451 451 | 
             
            See also
         | 
| 452 452 | 
             
            ---------------------------------------------------------------------------------------------------
         | 
| 453 | 
            -
            * [README-JA.md - README.md in Japanese( | 
| 453 | 
            +
            * [README-JA.md - README.md in Japanese(🇯🇵)](https://github.com/sisimai/rb-sisimai/blob/master/README-JA.md)
         | 
| 454 454 | 
             
            * [RFC3463 - Enhanced Mail System Status Codes](https://tools.ietf.org/html/rfc3463)
         | 
| 455 455 | 
             
            * [RFC3464 - An Extensible Message Format for Delivery Status Notifications](https://tools.ietf.org/html/rfc3464)
         | 
| 456 456 | 
             
            * [RFC3834 - Recommendations for Automatic Responses to Electronic Mail](https://tools.ietf.org/html/rfc3834)
         | 
    
        data/lib/sisimai/address.rb
    CHANGED
    
    | @@ -12,7 +12,7 @@ module Sisimai | |
| 12 12 | 
             
                  #   dtext           = NO-WS-CTL /     ; Non white space controls
         | 
| 13 13 | 
             
                  #                     %d33-90 /       ; The rest of the US-ASCII
         | 
| 14 14 | 
             
                  #                     %d94-126        ;  characters not including "[", "]", or "\"
         | 
| 15 | 
            -
                  re             = { | 
| 15 | 
            +
                  re             = {rfc5322: nil, ignored: nil, domain: nil}
         | 
| 16 16 | 
             
                  atom           = %r([a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)o
         | 
| 17 17 | 
             
                  quoted_string  = %r/"(?:\\[^\r\n]|[^\\"])*"/o
         | 
| 18 18 | 
             
                  domain_literal = %r/\[(?:\\[\x01-\x09\x0B-\x0c\x0e-\x7f]|[\x21-\x5a\x5e-\x7e])*\]/o
         | 
| @@ -33,7 +33,7 @@ module Sisimai | |
| 33 33 | 
             
                  :'quoted-string' => (1 << 1),    # "Neko, Nyaan"
         | 
| 34 34 | 
             
                  :'comment-block' => (1 << 2),    # (neko)
         | 
| 35 35 | 
             
                }.freeze
         | 
| 36 | 
            -
                Delimiters  = { | 
| 36 | 
            +
                Delimiters  = {'<' => 1, '>' => 1, '(' => 1, ')' => 1, '"' => 1, ',' => 1}.freeze
         | 
| 37 37 |  | 
| 38 38 | 
             
                # Return pseudo recipient or sender address
         | 
| 39 39 | 
             
                # @param    [Symbol] argv0  Address type: true = recipient, false = sender
         | 
| @@ -45,12 +45,10 @@ module Sisimai | |
| 45 45 |  | 
| 46 46 | 
             
                # Check that the argument is an email address or not
         | 
| 47 47 | 
             
                # @param    [String] email  Email address string
         | 
| 48 | 
            -
                # @return   [ | 
| 49 | 
            -
                #                           false: is not an email address
         | 
| 48 | 
            +
                # @return   [Boolean]       true: is an email address, false: is not an email address
         | 
| 50 49 | 
             
                def self.is_emailaddress(email)
         | 
| 51 | 
            -
                  return false  | 
| 52 | 
            -
                  return false if email =~ %r/(?:[\x00-\x1f]|\x1f)/
         | 
| 53 | 
            -
                  return false if email.size > 254
         | 
| 50 | 
            +
                  return false if email.is_a?(::String) == false
         | 
| 51 | 
            +
                  return false if email =~ %r/(?:[\x00-\x1f]|\x1f)/ || email.size > 254
         | 
| 54 52 | 
             
                  return true  if email =~ Re[:ignored]
         | 
| 55 53 | 
             
                  return false
         | 
| 56 54 | 
             
                end
         | 
| @@ -60,9 +58,7 @@ module Sisimai | |
| 60 58 | 
             
                # @return   [True,False]    true: mailer-daemon
         | 
| 61 59 | 
             
                #                           false: Not mailer-daemon
         | 
| 62 60 | 
             
                def self.is_mailerdaemon(argv0 = nil)
         | 
| 63 | 
            -
                  return false  | 
| 64 | 
            -
                  return false unless argv0.size > 0
         | 
| 65 | 
            -
                  return false unless argv0.is_a?(::String)
         | 
| 61 | 
            +
                  return false if argv0.to_s == "" || argv0.is_a?(::String) == false
         | 
| 66 62 |  | 
| 67 63 | 
             
                  email = argv0.downcase
         | 
| 68 64 | 
             
                  postmaster = [
         | 
| @@ -71,8 +67,7 @@ module Sisimai | |
| 71 67 | 
             
                  ].freeze
         | 
| 72 68 |  | 
| 73 69 | 
             
                  return true if postmaster.any? { |a| email.include?(a) }
         | 
| 74 | 
            -
                  return true if email == 'mailer-daemon'
         | 
| 75 | 
            -
                  return true if email == 'postmaster'
         | 
| 70 | 
            +
                  return true if email == 'mailer-daemon' || email == 'postmaster'
         | 
| 76 71 | 
             
                  return false
         | 
| 77 72 | 
             
                end
         | 
| 78 73 |  | 
| @@ -87,7 +82,7 @@ module Sisimai | |
| 87 82 | 
             
                  #   #=> [{ address: 'neko@example.org', name: 'Neko', comment: '(nyaan)'}]
         | 
| 88 83 | 
             
                  return nil unless argv1
         | 
| 89 84 |  | 
| 90 | 
            -
                  emailtable = { | 
| 85 | 
            +
                  emailtable = {address: '', name: '', comment: ''}
         | 
| 91 86 | 
             
                  addrtables = []
         | 
| 92 87 | 
             
                  readbuffer = []
         | 
| 93 88 | 
             
                  readcursor = 0
         | 
| @@ -109,20 +104,20 @@ module Sisimai | |
| 109 104 | 
             
                          # An email address has already been picked
         | 
| 110 105 | 
             
                          if readcursor & Indicators[:'comment-block'] > 0
         | 
| 111 106 | 
             
                            # The cursor is in the comment block (Neko, Nyaan)
         | 
| 112 | 
            -
                            v[:comment]  | 
| 107 | 
            +
                            v[:comment] += e
         | 
| 113 108 | 
             
                          elsif readcursor & Indicators[:'quoted-string'] > 0
         | 
| 114 109 | 
             
                            # "Neko, Nyaan"
         | 
| 115 | 
            -
                            v[:name]  | 
| 110 | 
            +
                            v[:name] += e
         | 
| 116 111 | 
             
                          else
         | 
| 117 112 | 
             
                            # The cursor is not in neither the quoted-string nor the comment block
         | 
| 118 113 | 
             
                            readcursor = 0  # reset cursor position
         | 
| 119 114 | 
             
                            readbuffer << v
         | 
| 120 | 
            -
                            v = { | 
| 115 | 
            +
                            v = {address: '', name: '', comment: ''}
         | 
| 121 116 | 
             
                            p = ''
         | 
| 122 117 | 
             
                          end
         | 
| 123 118 | 
             
                        else
         | 
| 124 119 | 
             
                          # "Neko, Nyaan" <neko@nyaan.example.org> OR <"neko,nyaan"@example.org>
         | 
| 125 | 
            -
                          p.empty? ? (v[:name]  | 
| 120 | 
            +
                          p.empty? ? (v[:name] += e) : (v[p] += e)
         | 
| 126 121 | 
             
                        end
         | 
| 127 122 | 
             
                        next
         | 
| 128 123 | 
             
                      end # End of if(',')
         | 
| @@ -130,11 +125,11 @@ module Sisimai | |
| 130 125 | 
             
                      if e == '<'
         | 
| 131 126 | 
             
                        # <: The beginning of an email address or not
         | 
| 132 127 | 
             
                        if v[:address].size > 0
         | 
| 133 | 
            -
                          p.empty? ? (v[:name]  | 
| 128 | 
            +
                          p.empty? ? (v[:name] += e) : (v[p] += e)
         | 
| 134 129 | 
             
                        else
         | 
| 135 130 | 
             
                          # <neko@nyaan.example.org>
         | 
| 136 131 | 
             
                          readcursor |= Indicators[:'email-address']
         | 
| 137 | 
            -
                          v[:address]  | 
| 132 | 
            +
                          v[:address] += e
         | 
| 138 133 | 
             
                          p = :address
         | 
| 139 134 | 
             
                        end
         | 
| 140 135 | 
             
                        next
         | 
| @@ -146,11 +141,11 @@ module Sisimai | |
| 146 141 | 
             
                        if readcursor & Indicators[:'email-address'] > 0
         | 
| 147 142 | 
             
                          # <neko@example.org>
         | 
| 148 143 | 
             
                          readcursor &= ~Indicators[:'email-address']
         | 
| 149 | 
            -
                          v[:address]  | 
| 144 | 
            +
                          v[:address] += e
         | 
| 150 145 | 
             
                          p = ''
         | 
| 151 146 | 
             
                        else
         | 
| 152 147 | 
             
                          # a comment block or a display name
         | 
| 153 | 
            -
                          p.empty? ? (v[:name]  | 
| 148 | 
            +
                          p.empty? ? (v[:name] == e) : (v[:comment] -= e)
         | 
| 154 149 | 
             
                        end
         | 
| 155 150 | 
             
                        next
         | 
| 156 151 | 
             
                      end # End of if('>')
         | 
| @@ -161,27 +156,27 @@ module Sisimai | |
| 161 156 | 
             
                          # <"neko(nyaan)"@example.org> or <neko(nyaan)@example.org>
         | 
| 162 157 | 
             
                          if v[:address].include?('"')
         | 
| 163 158 | 
             
                            # Quoted local part: <"neko(nyaan)"@example.org>
         | 
| 164 | 
            -
                            v[:address]  | 
| 159 | 
            +
                            v[:address] += e
         | 
| 165 160 | 
             
                          else
         | 
| 166 161 | 
             
                            # Comment: <neko(nyaan)@example.org>
         | 
| 167 162 | 
             
                            readcursor |= Indicators[:'comment-block']
         | 
| 168 | 
            -
                            v[:comment]  | 
| 169 | 
            -
                            v[:comment]  | 
| 163 | 
            +
                            v[:comment] += ' ' if v[:comment].end_with?(')')
         | 
| 164 | 
            +
                            v[:comment] += e
         | 
| 170 165 | 
             
                            p = :comment
         | 
| 171 166 | 
             
                          end
         | 
| 172 167 | 
             
                        elsif readcursor & Indicators[:'comment-block'] > 0
         | 
| 173 168 | 
             
                          # Comment at the outside of an email address (...(...)
         | 
| 174 | 
            -
                          v[:comment]  | 
| 175 | 
            -
                          v[:comment]  | 
| 169 | 
            +
                          v[:comment] += ' ' if v[:comment].end_with?(')')
         | 
| 170 | 
            +
                          v[:comment] += e
         | 
| 176 171 |  | 
| 177 172 | 
             
                        elsif readcursor & Indicators[:'quoted-string'] > 0
         | 
| 178 173 | 
             
                          # "Neko, Nyaan(cat)", Deal as a display name
         | 
| 179 | 
            -
                          v[:name]  | 
| 174 | 
            +
                          v[:name] += e
         | 
| 180 175 | 
             
                        else
         | 
| 181 176 | 
             
                          # The beginning of a comment block
         | 
| 182 177 | 
             
                          readcursor |= Indicators[:'comment-block']
         | 
| 183 | 
            -
                          v[:comment]  | 
| 184 | 
            -
                          v[:comment]  | 
| 178 | 
            +
                          v[:comment] += ' ' if v[:comment].end_with?(')')
         | 
| 179 | 
            +
                          v[:comment] += e
         | 
| 185 180 | 
             
                          p = :comment
         | 
| 186 181 | 
             
                        end
         | 
| 187 182 | 
             
                        next
         | 
| @@ -193,22 +188,22 @@ module Sisimai | |
| 193 188 | 
             
                          # <"neko(nyaan)"@example.org> OR <neko(nyaan)@example.org>
         | 
| 194 189 | 
             
                          if v[:address].include?('"')
         | 
| 195 190 | 
             
                            # Quoted string in the local part: <"neko(nyaan)"@example.org>
         | 
| 196 | 
            -
                            v[:address]  | 
| 191 | 
            +
                            v[:address] += e
         | 
| 197 192 | 
             
                          else
         | 
| 198 193 | 
             
                            # Comment: <neko(nyaan)@example.org>
         | 
| 199 194 | 
             
                            readcursor &= ~Indicators[:'comment-block']
         | 
| 200 | 
            -
                            v[:comment]  | 
| 195 | 
            +
                            v[:comment] += e
         | 
| 201 196 | 
             
                            p = :address
         | 
| 202 197 | 
             
                          end
         | 
| 203 198 | 
             
                        elsif readcursor & Indicators[:'comment-block'] > 0
         | 
| 204 199 | 
             
                          # Comment at the outside of an email address (...(...)
         | 
| 205 200 | 
             
                          readcursor &= ~Indicators[:'comment-block']
         | 
| 206 | 
            -
                          v[:comment]  | 
| 201 | 
            +
                          v[:comment] += e
         | 
| 207 202 | 
             
                          p = ''
         | 
| 208 203 | 
             
                        else
         | 
| 209 204 | 
             
                          # Deal as a display name
         | 
| 210 205 | 
             
                          readcursor &= ~Indicators[:'comment-block']
         | 
| 211 | 
            -
                          v[:name]  | 
| 206 | 
            +
                          v[:name] += e
         | 
| 212 207 | 
             
                          p = ''
         | 
| 213 208 | 
             
                        end
         | 
| 214 209 | 
             
                        next
         | 
| @@ -218,10 +213,10 @@ module Sisimai | |
| 218 213 | 
             
                        # The beginning or the end of a quoted-string
         | 
| 219 214 | 
             
                        if p.size > 0
         | 
| 220 215 | 
             
                          # email-address or comment-block
         | 
| 221 | 
            -
                          v[p]  | 
| 216 | 
            +
                          v[p] += e
         | 
| 222 217 | 
             
                        else
         | 
| 223 218 | 
             
                          # Display name like "Neko, Nyaan"
         | 
| 224 | 
            -
                          v[:name]  | 
| 219 | 
            +
                          v[:name] += e
         | 
| 225 220 | 
             
                          next unless readcursor & Indicators[:'quoted-string'] > 0
         | 
| 226 221 | 
             
                          next if v[:name].end_with?(%Q|\x5c"|) # "Neko, Nyaan \"...
         | 
| 227 222 | 
             
                          readcursor &= ~Indicators[:'quoted-string']
         | 
| @@ -231,7 +226,7 @@ module Sisimai | |
| 231 226 | 
             
                      end # End of if('"')
         | 
| 232 227 | 
             
                    else
         | 
| 233 228 | 
             
                      # The character is not a delimiter
         | 
| 234 | 
            -
                      p.empty? ? (v[:name]  | 
| 229 | 
            +
                      p.empty? ? (v[:name] += e) : (v[p] += e)
         | 
| 235 230 | 
             
                      next
         | 
| 236 231 | 
             
                    end
         | 
| 237 232 | 
             
                  end
         | 
| @@ -283,7 +278,7 @@ module Sisimai | |
| 283 278 | 
             
                      e.delete(:comment)
         | 
| 284 279 | 
             
                    else
         | 
| 285 280 | 
             
                      # Remove double-quotations, trailing spaces.
         | 
| 286 | 
            -
                      [:name, :comment].each { |f| e[f].strip | 
| 281 | 
            +
                      [:name, :comment].each { |f| e[f] = e[f].strip }
         | 
| 287 282 | 
             
                      e[:comment] = '' unless e[:comment] =~ /\A[(].+[)]/
         | 
| 288 283 | 
             
                      e[:name].squeeze!(' ')     unless e[:name] =~ /\A["].+["]\z/
         | 
| 289 284 | 
             
                      e[:name].sub!(/\A["]/, '') unless e[:name] =~ /\A["].+["][@]/
         | 
| @@ -301,8 +296,8 @@ module Sisimai | |
| 301 296 | 
             
                # @return   [String]        Email address without comment, brackets
         | 
| 302 297 | 
             
                # @example  s3s4('<neko@example.cat>') #=> 'neko@example.cat'
         | 
| 303 298 | 
             
                def self.s3s4(input)
         | 
| 304 | 
            -
                  return  | 
| 305 | 
            -
                  return  | 
| 299 | 
            +
                  return "" if input.to_s == ""
         | 
| 300 | 
            +
                  return "" if input.is_a?(Object::String) == false
         | 
| 306 301 |  | 
| 307 302 | 
             
                  addrs = Sisimai::Address.find(input, true) || []
         | 
| 308 303 | 
             
                  return input if addrs.empty?
         | 
| @@ -315,8 +310,8 @@ module Sisimai | |
| 315 310 | 
             
                # @example  Expand VERP address
         | 
| 316 311 | 
             
                #   expand_verp('bounce+neko=example.org@example.org') #=> 'neko@example.org'
         | 
| 317 312 | 
             
                def self.expand_verp(email)
         | 
| 318 | 
            -
                  return  | 
| 319 | 
            -
                  return  | 
| 313 | 
            +
                  return "" unless email.is_a? Object::String
         | 
| 314 | 
            +
                  return "" unless cv = email.split('@', 2).first.match(/\A[-\w]+?[+](\w[-.\w]+\w)[=](\w[-.\w]+\w)\z/)
         | 
| 320 315 | 
             
                  verp0 = cv[1] + '@' + cv[2]
         | 
| 321 316 | 
             
                  return verp0 if Sisimai::Address.is_emailaddress(verp0)
         | 
| 322 317 | 
             
                end
         | 
| @@ -327,10 +322,10 @@ module Sisimai | |
| 327 322 | 
             
                # @example  Expand alias
         | 
| 328 323 | 
             
                #   expand_alias('neko+straycat@example.org') #=> 'neko@example.org'
         | 
| 329 324 | 
             
                def self.expand_alias(email)
         | 
| 330 | 
            -
                  return  | 
| 325 | 
            +
                  return "" unless Sisimai::Address.is_emailaddress(email)
         | 
| 331 326 |  | 
| 332 327 | 
             
                  local = email.split('@')
         | 
| 333 | 
            -
                  return  | 
| 328 | 
            +
                  return "" unless cv = local[0].match(/\A([-\w]+?)[+].+\z/)
         | 
| 334 329 | 
             
                  return cv[1] + '@' + local[1]
         | 
| 335 330 | 
             
                end
         | 
| 336 331 |  | 
| @@ -347,11 +342,9 @@ module Sisimai | |
| 347 342 | 
             
                # Constructor of Sisimai::Address
         | 
| 348 343 | 
             
                # @param    [Hash] argvs        Email address, name, and other elements
         | 
| 349 344 | 
             
                # @return   [Sisimai::Address]  Object or nil when the email address was not valid.
         | 
| 350 | 
            -
                # @example  new( | 
| 345 | 
            +
                # @example  new(address: 'neko@example.org', name: 'Neko', comment: '(nyaan)') # => Sisimai::Address object
         | 
| 351 346 | 
             
                def initialize(argvs)
         | 
| 352 | 
            -
                  return nil  | 
| 353 | 
            -
                  return nil unless argvs[:address]
         | 
| 354 | 
            -
                  return nil if argvs[:address].empty?
         | 
| 347 | 
            +
                  return nil if argvs.is_a?(Hash) == false || argvs[:address].nil? || argvs[:address].empty?
         | 
| 355 348 |  | 
| 356 349 | 
             
                  heads = ['<']
         | 
| 357 350 | 
             
                  tails = ['>', ',', '.', ';']
         | 
| @@ -364,10 +357,10 @@ module Sisimai | |
| 364 357 | 
             
                    email = Sisimai::Address.expand_verp(argvs[:address])
         | 
| 365 358 | 
             
                    aname = nil
         | 
| 366 359 |  | 
| 367 | 
            -
                     | 
| 360 | 
            +
                    if email.empty?
         | 
| 368 361 | 
             
                      # Is not VERP address, try to expand the address as an alias
         | 
| 369 | 
            -
                      email = Sisimai::Address.expand_alias(argvs[:address]) | 
| 370 | 
            -
                      aname = true  | 
| 362 | 
            +
                      email = Sisimai::Address.expand_alias(argvs[:address])
         | 
| 363 | 
            +
                      aname = true if email.empty? == false
         | 
| 371 364 | 
             
                    end
         | 
| 372 365 |  | 
| 373 366 | 
             
                    if email.include?('@')
         | 
| @@ -422,15 +415,11 @@ module Sisimai | |
| 422 415 |  | 
| 423 416 | 
             
                # Returns the value of address as String
         | 
| 424 417 | 
             
                # @return [String] Email address
         | 
| 425 | 
            -
                def to_json(*)
         | 
| 426 | 
            -
                  return self.address.to_s
         | 
| 427 | 
            -
                end
         | 
| 418 | 
            +
                def to_json(*); return self.address.to_s; end
         | 
| 428 419 |  | 
| 429 420 | 
             
                # Returns the value of address as String
         | 
| 430 421 | 
             
                # @return [String] Email address
         | 
| 431 | 
            -
                def to_s
         | 
| 432 | 
            -
                  return self.address.to_s
         | 
| 433 | 
            -
                end
         | 
| 422 | 
            +
                def to_s; return self.address.to_s; end
         | 
| 434 423 |  | 
| 435 424 | 
             
              end
         | 
| 436 425 | 
             
            end
         | 
    
        data/lib/sisimai/arf.rb
    CHANGED
    
    | @@ -53,12 +53,9 @@ module Sisimai | |
| 53 53 | 
             
                      end
         | 
| 54 54 | 
             
                    end
         | 
| 55 55 |  | 
| 56 | 
            -
                     | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
                      return true if heads["x-apple-unsubscribe"] == "true"
         | 
| 60 | 
            -
                      break
         | 
| 61 | 
            -
                    end
         | 
| 56 | 
            +
                    # X-Apple-Unsubscribe: true
         | 
| 57 | 
            +
                    return false unless heads.has_key?("x-apple-unsubscribe")
         | 
| 58 | 
            +
                    return true  if heads["x-apple-unsubscribe"] == "true"
         | 
| 62 59 | 
             
                    return false
         | 
| 63 60 | 
             
                  end
         | 
| 64 61 |  | 
| @@ -70,7 +67,7 @@ module Sisimai | |
| 70 67 | 
             
                  def inquire(mhead, mbody)
         | 
| 71 68 | 
             
                    return nil unless self.is_arf(mhead)
         | 
| 72 69 |  | 
| 73 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 70 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = dscontents[-1]
         | 
| 74 71 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 75 72 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 76 73 | 
             
                    reportpart = false
         | 
| @@ -80,7 +77,6 @@ module Sisimai | |
| 80 77 | 
             
                    remotehost = ""   # The value of "Source-IP" field
         | 
| 81 78 | 
             
                    reportedby = ""   # The value of "Reporting-MTA" field
         | 
| 82 79 | 
             
                    anotherone = ""   # Other fields(append to Diagnosis)
         | 
| 83 | 
            -
                    v = dscontents[-1]
         | 
| 84 80 |  | 
| 85 81 | 
             
                    # 3.1.  Required Fields
         | 
| 86 82 | 
             
                    #
         | 
| @@ -115,13 +111,12 @@ module Sisimai | |
| 115 111 | 
             
                          # this is an autogenerated email abuse complaint regarding your network.
         | 
| 116 112 | 
             
                          next unless Sisimai::String.aligned(r, f)
         | 
| 117 113 | 
             
                          readcursor |= Indicators[:deliverystatus]
         | 
| 118 | 
            -
                          v["diagnosis"]  | 
| 114 | 
            +
                          v["diagnosis"] += " #{e}"
         | 
| 119 115 | 
             
                          break
         | 
| 120 116 | 
             
                        end
         | 
| 121 117 | 
             
                        next
         | 
| 122 118 | 
             
                      end
         | 
| 123 | 
            -
                      next  | 
| 124 | 
            -
                      next if e.empty?
         | 
| 119 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) > 0 || e.empty?
         | 
| 125 120 | 
             
                      if e == ReportFrom then reportpart = true; next; end
         | 
| 126 121 |  | 
| 127 122 | 
             
                      if reportpart
         | 
| @@ -158,12 +153,12 @@ module Sisimai | |
| 158 153 | 
             
                          #
         | 
| 159 154 | 
             
                          # Authentication-Results: mail.example.com;
         | 
| 160 155 | 
             
                          #   spf=fail smtp.mail=somespammer@example.com
         | 
| 161 | 
            -
                          anotherone  | 
| 156 | 
            +
                          anotherone += "#{e}, "
         | 
| 162 157 |  | 
| 163 158 | 
             
                        elsif e.start_with?("User-Agent: ")
         | 
| 164 159 | 
             
                          # The header field MUST appear exactly once.
         | 
| 165 160 | 
             
                          # User-Agent: SomeGenerator/1.0
         | 
| 166 | 
            -
                          anotherone  | 
| 161 | 
            +
                          anotherone += "#{e}, "
         | 
| 167 162 |  | 
| 168 163 | 
             
                        elsif e.start_with?("Received-Date: ") || e.start_with?("Arrival-Date: ")
         | 
| 169 164 | 
             
                          # Arrival-Date header is optional and MUST NOT appear more than once.
         | 
| @@ -185,11 +180,11 @@ module Sisimai | |
| 185 180 | 
             
                        elsif e.start_with?("Original-Mail-From: ")
         | 
| 186 181 | 
             
                          # the header is optional and MUST NOT appear more than once.
         | 
| 187 182 | 
             
                          # Original-Mail-From: <somespammer@example.net>
         | 
| 188 | 
            -
                          anotherone  | 
| 183 | 
            +
                          anotherone += "#{e}, "
         | 
| 189 184 | 
             
                        end
         | 
| 190 185 | 
             
                      else
         | 
| 191 186 | 
             
                        # Messages before "Content-Type: message/feedback-report" part
         | 
| 192 | 
            -
                        v["diagnosis"]  | 
| 187 | 
            +
                        v["diagnosis"] += " #{e}"
         | 
| 193 188 | 
             
                      end
         | 
| 194 189 |  | 
| 195 190 | 
             
                      while recipients == 0
         | 
| @@ -220,7 +215,7 @@ module Sisimai | |
| 220 215 | 
             
                      end
         | 
| 221 216 | 
             
                      return nil if recipients == 0
         | 
| 222 217 |  | 
| 223 | 
            -
                      anotherone = ":  | 
| 218 | 
            +
                      anotherone = ": #{Sisimai::String.sweep(anotherone)}" if anotherone != ""
         | 
| 224 219 | 
             
                      anotherone = anotherone.chop if anotherone[-1, 1] == ","
         | 
| 225 220 |  | 
| 226 221 | 
             
                      j = -1
         | 
    
        data/lib/sisimai/datetime.rb
    CHANGED
    
    | @@ -4,34 +4,7 @@ module Sisimai | |
| 4 4 | 
             
                require 'date'
         | 
| 5 5 |  | 
| 6 6 | 
             
                class << self
         | 
| 7 | 
            -
                   | 
| 8 | 
            -
                  BASE_Y = 365.2425 # 1 year = 365.2425 days
         | 
| 9 | 
            -
                  BASE_L = 29.53059 # 1 lunar month = 29.53059 days
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                  CONST_P = 4 * Math.atan2(1, 1)  # PI, 3.1415926535
         | 
| 12 | 
            -
                  CONST_E = Math.exp(1)           # e, Napier's constant
         | 
| 13 | 
            -
                  TZ_OFFSET = 54000               # Max time zone offset, 54000 seconds
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  TimeUnit = {
         | 
| 16 | 
            -
                    'o' => (BASE_D * BASE_Y * 4), # Olympiad, 4 years
         | 
| 17 | 
            -
                    'y' => (BASE_D * BASE_Y),     # Year, Gregorian Calendar
         | 
| 18 | 
            -
                    'q' => (BASE_D * BASE_Y / 4), # Quarter, year/4
         | 
| 19 | 
            -
                    'l' => (BASE_D * BASE_L),     # Lunar month
         | 
| 20 | 
            -
                    'f' => (BASE_D * 14),         # Fortnight, 2 weeks
         | 
| 21 | 
            -
                    'w' => (BASE_D * 7),          # Week, 604800 seconds
         | 
| 22 | 
            -
                    'd' => BASE_D,                # Day
         | 
| 23 | 
            -
                    'h' => 3600,                  # Hour
         | 
| 24 | 
            -
                    'b' => 86.4,                  # Beat, Swatch internet time: 1000b = 1d
         | 
| 25 | 
            -
                    'm' => 60,                    # Minute,
         | 
| 26 | 
            -
                    's' => 1,                     # Second
         | 
| 27 | 
            -
                  }.freeze
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  MathematicalConstant = {
         | 
| 30 | 
            -
                    'e' => CONST_E,
         | 
| 31 | 
            -
                    'p' => CONST_P,
         | 
| 32 | 
            -
                    'g' => CONST_E**CONST_P,
         | 
| 33 | 
            -
                  }.freeze
         | 
| 34 | 
            -
             | 
| 7 | 
            +
                  TZ_OFFSET = 54000 # Max time zone offset, 54000 seconds
         | 
| 35 8 | 
             
                  MonthName = {
         | 
| 36 9 | 
             
                    full: %w[January February March April May June July August September October November December],
         | 
| 37 10 | 
             
                    abbr: %w[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec],
         | 
| @@ -191,12 +164,9 @@ module Sisimai | |
| 191 164 | 
             
                  #   parse("2015-11-03T23:34:45 Tue")    #=> Tue, 3 Nov 2015 23:34:45 +0900
         | 
| 192 165 | 
             
                  #   parse("Tue, Nov 3 2015 2:2:2")      #=> Tue, 3 Nov 2015 02:02:02 +0900
         | 
| 193 166 | 
             
                  def parse(argv1)
         | 
| 194 | 
            -
                    return  | 
| 195 | 
            -
                    return nil if argv1.empty?
         | 
| 167 | 
            +
                    return "" if argv1.is_a?(::String) == false || argv1.empty?
         | 
| 196 168 |  | 
| 197 | 
            -
                    datestring = argv1
         | 
| 198 | 
            -
                    datestring.sub!(/[,](\d+)/, ', \1') # Thu,13 -> Thu, 13
         | 
| 199 | 
            -
                    datestring.sub!(/(\d{1,2}),/, '\1') # Apr,29 -> Apr 29
         | 
| 169 | 
            +
                    datestring = argv1.sub(/[,](\d+)/, ', \1').sub(/(\d{1,2}),/, '\1')
         | 
| 200 170 | 
             
                    timetokens = datestring.split(' ')
         | 
| 201 171 | 
             
                    afternoon1 = 0    # (Integer) After noon flag
         | 
| 202 172 | 
             
                    altervalue = {}   # (Hash) To store alternative values
         | 
| @@ -267,7 +237,7 @@ module Sisimai | |
| 267 237 |  | 
| 268 238 | 
             
                        elsif p =~ /\A[(]?[A-Z]{2,5}[)]?\z/
         | 
| 269 239 | 
             
                          # Timezone abbreviation; JST, GMT, UTC, ...
         | 
| 270 | 
            -
                          v[:z] ||= abbr2tz(p)  | 
| 240 | 
            +
                          v[:z] ||= abbr2tz(p); v[:z] = "+0000" if v[:z].empty?
         | 
| 271 241 | 
             
                        else
         | 
| 272 242 | 
             
                          # Other date format
         | 
| 273 243 | 
             
                          if cr = p.match(%r|\A(\d{4})[-/](\d{1,2})[-/](\d{1,2})\z|)
         | 
| @@ -333,13 +303,9 @@ module Sisimai | |
| 333 303 | 
             
                    if v.value?(nil)
         | 
| 334 304 | 
             
                      # Strange date format
         | 
| 335 305 | 
             
                      warn sprintf(' ***warning: Strange date format [%s]', datestring)
         | 
| 336 | 
            -
                      return  | 
| 337 | 
            -
                    end
         | 
| 338 | 
            -
             | 
| 339 | 
            -
                    if v[:Y].to_i < 1902 || v[:Y].to_i > 2037
         | 
| 340 | 
            -
                      # -(2^31) ~ (2^31)
         | 
| 341 | 
            -
                      return nil
         | 
| 306 | 
            +
                      return ""
         | 
| 342 307 | 
             
                    end
         | 
| 308 | 
            +
                    return "" if v[:Y].to_i < 1902 || v[:Y].to_i > 2037 # -(2^31) ~ (2^31)
         | 
| 343 309 |  | 
| 344 310 | 
             
                    # Build date string
         | 
| 345 311 | 
             
                    #   Thu, 29 Apr 2004 10:01:11 +0900
         | 
| @@ -348,23 +314,23 @@ module Sisimai | |
| 348 314 |  | 
| 349 315 | 
             
                  # Abbreviation -> Tiemzone
         | 
| 350 316 | 
             
                  # @param    [String] argv1  Abbr. e.g.) JST, GMT, PDT
         | 
| 351 | 
            -
                  # @return   [String | 
| 352 | 
            -
                  #                           not supported abbreviation
         | 
| 317 | 
            +
                  # @return   [String]        +0900, +0000, -0600 or an empty string if the argument is invalid
         | 
| 318 | 
            +
                  #                           format or not supported abbreviation
         | 
| 353 319 | 
             
                  # @example  Get the timezone string of "JST"
         | 
| 354 320 | 
             
                  #   abbr2tz('JST')  #=> '+0900'
         | 
| 355 321 | 
             
                  def abbr2tz(argv1)
         | 
| 356 | 
            -
                    return  | 
| 357 | 
            -
                    return TimeZones[argv1]
         | 
| 322 | 
            +
                    return "" if argv1.is_a?(::String) == false
         | 
| 323 | 
            +
                    return TimeZones[argv1] || ""
         | 
| 358 324 | 
             
                  end
         | 
| 359 325 |  | 
| 360 326 | 
             
                  # Convert to second
         | 
| 361 327 | 
             
                  # @param    [String] argv1  Timezone string e.g) +0900
         | 
| 362 | 
            -
                  # @return   [Integer | 
| 328 | 
            +
                  # @return   [Integer]       n: seconds or 0 when the argument is invalid format
         | 
| 363 329 | 
             
                  # @see      second2tz
         | 
| 364 330 | 
             
                  # @example  Convert '+0900' to seconds
         | 
| 365 331 | 
             
                  #   tz2second('+0900')  #=> 32400
         | 
| 366 332 | 
             
                  def tz2second(argv1)
         | 
| 367 | 
            -
                    return  | 
| 333 | 
            +
                    return 0 if argv1.is_a?(::String) == false
         | 
| 368 334 | 
             
                    ztime = 0
         | 
| 369 335 |  | 
| 370 336 | 
             
                    if cr = argv1.match(/\A([-+])(\d)(\d)(\d{2})\z/)
         | 
| @@ -378,13 +344,13 @@ module Sisimai | |
| 378 344 | 
             
                      ztime += (digit[:'minutes'] * 60)
         | 
| 379 345 | 
             
                      ztime *= -1 if digit[:'operator'] == '-'
         | 
| 380 346 |  | 
| 381 | 
            -
                      return  | 
| 347 | 
            +
                      return 0 if ztime.abs > TZ_OFFSET
         | 
| 382 348 | 
             
                      return ztime
         | 
| 383 349 |  | 
| 384 350 | 
             
                    elsif argv1 =~ /\A[A-Za-z]+\z/
         | 
| 385 351 | 
             
                      return tz2second(TimeZones[argv1])
         | 
| 386 352 | 
             
                    else
         | 
| 387 | 
            -
                      return  | 
| 353 | 
            +
                      return 0
         | 
| 388 354 | 
             
                    end
         | 
| 389 355 | 
             
                  end
         | 
| 390 356 |  | 
| @@ -396,9 +362,9 @@ module Sisimai | |
| 396 362 | 
             
                  #   second2tz(12345)    #=> '+0325'
         | 
| 397 363 | 
             
                  def second2tz(argv1)
         | 
| 398 364 | 
             
                    return '+0000' unless argv1.is_a?(::Integer)
         | 
| 399 | 
            -
                    return  | 
| 365 | 
            +
                    return "" if argv1.abs > TZ_OFFSET  # UTC+14 + 1(DST?)
         | 
| 400 366 |  | 
| 401 | 
            -
                    digit = { | 
| 367 | 
            +
                    digit = {:operator => '+'}
         | 
| 402 368 | 
             
                    digit[:operator] = '-' if argv1 < 0
         | 
| 403 369 | 
             
                    digit[:hours]    = (argv1.abs / 3600).to_i
         | 
| 404 370 | 
             
                    digit[:minutes]  = ((argv1.abs % 3600) / 60).to_i
         | 
    
        data/lib/sisimai/fact/json.rb
    CHANGED
    
    | @@ -6,10 +6,10 @@ module Sisimai | |
| 6 6 | 
             
                  class << self
         | 
| 7 7 | 
             
                    # Serializer (JSON)
         | 
| 8 8 | 
             
                    # @param    [Sisimai::Fact] argvs Object
         | 
| 9 | 
            -
                    # @return   [String | 
| 9 | 
            +
                    # @return   [String]              Dumped data or an empty string if the argument is missing
         | 
| 10 10 | 
             
                    def dump(argvs)
         | 
| 11 | 
            -
                      return  | 
| 12 | 
            -
                      return  | 
| 11 | 
            +
                      return "" unless argvs
         | 
| 12 | 
            +
                      return "" unless argvs.is_a? Sisimai::Fact
         | 
| 13 13 |  | 
| 14 14 | 
             
                      if RUBY_PLATFORM.start_with?('java')
         | 
| 15 15 | 
             
                        # java-based ruby environment like JRuby.
         | 
| @@ -17,7 +17,7 @@ module Sisimai | |
| 17 17 | 
             
                          require 'jrjackson'
         | 
| 18 18 | 
             
                          jsonstring = JrJackson::Json.dump(argvs.damn)
         | 
| 19 19 | 
             
                        rescue StandardError => ce
         | 
| 20 | 
            -
                          warn '***warning: Failed to JrJackson::Json.dump: '  | 
| 20 | 
            +
                          warn '***warning: Failed to JrJackson::Json.dump: ' + ce.to_s
         | 
| 21 21 | 
             
                        end
         | 
| 22 22 | 
             
                      else
         | 
| 23 23 | 
             
                        # MRI
         | 
| @@ -25,7 +25,7 @@ module Sisimai | |
| 25 25 | 
             
                          require 'oj'
         | 
| 26 26 | 
             
                          jsonstring = Oj.dump(argvs.damn, :mode => :compat)
         | 
| 27 27 | 
             
                        rescue StandardError => ce
         | 
| 28 | 
            -
                          warn '***warning: Failed to Oj.dump: '  | 
| 28 | 
            +
                          warn '***warning: Failed to Oj.dump: ' + ce.to_s
         | 
| 29 29 | 
             
                        end
         | 
| 30 30 | 
             
                      end
         | 
| 31 31 |  |