root/platform/tdiary/util/posttdiary/posttdiary.rb @ 7079

Revision 7079, 6.1 kB (checked in by drry, 5 years ago)

platform/tdiary/util/posttdiary/posttdiary.rb:

  • Net::HTTP#get/post の HTTP ヘッダがハッシュになっていなかったのを直しました。
  • 正規表現を修正しました。
  • いくつかの冗長な部分を簡略化しました。
  • インデントの修整をしました。
  • ほか。
Line 
1#!/usr/bin/env ruby
2$KCODE= 'e'
3#
4# posttdiary: update tDiary via e-mail. $Revision: 1.5 $
5#
6# Copyright (C) 2002, All right reserved by TADA Tadashi <sho@spc.gr.jp>
7# You can redistribute it and/or modify it under GPL2.
8#
9
10def usage
11        <<-TEXT.gsub( /^\t{2}/, '' )
12                #{File::basename __FILE__}: update tDiary via e-mail.
13                usage: ruby #{File::basename __FILE__} [options] <url> [user] [passwd]
14                arguments:
15                  url:    update.rb's URL of your diary.
16                  user:   user ID of your diary updating.
17                  passwd: password of your diary updating.
18                          If To: field of the mail likes "user-passwd@example.com",
19                          you can omit user and passwd arguments.
20                options:
21                  --image-path,   -i: directory of image saving into.
22                  --image-url,    -u: URL of image.
23                          You have to specify both options when using images.
24                  --image-format, -f: format of image tag specified image serial
25                          number as '$0' and image url as '$1'.
26                          default format is ' <img class="photo" src="$1" alt="">'.
27                  --use-subject,  -s: use mail subject to subtitle.
28                          and insert image between subtitle and body.
29        TEXT
30end
31
32def image_list( date, path )
33        image_path = []
34        Dir.foreach( path ) do |file|
35                if file =~ /(\d{8,})_(\d+)\./ and $1 == date then
36                        image_path[$2.to_i] = file
37                end
38        end
39        image_path
40end
41
42def bmp_to_png( bmp )
43        png = bmp.sub( /\.bmp$/, '.png' )
44        begin
45                require 'magick'
46                img = Magick::Image::new( bmp )
47                img.write( 'magick' => 'png', 'filename' => png )
48        rescue LoadError
49                system( "convert #{bmp} #{png}" )
50        end
51        if FileTest::exist?( png )
52                File::delete( bmp )
53                png
54        else
55                bmp
56        end
57end
58
59begin
60
61        raise usage if ARGV.length < 1
62
63        require 'getoptlong'
64        parser = GetoptLong::new
65        image_dir = nil
66        image_url = nil
67        image_format = ' <img class="photo" src="$1" alt="">'
68        use_subject = false
69        parser.set_options(
70                ['--image-path',   '-i', GetoptLong::REQUIRED_ARGUMENT],
71                ['--image-url',    '-u', GetoptLong::REQUIRED_ARGUMENT],
72                ['--image-format', '-f', GetoptLong::REQUIRED_ARGUMENT],
73                ['--use-subject',  '-s', GetoptLong::NO_ARGUMENT]
74        )
75        begin
76                parser.each do |opt, arg|
77                        case opt
78                        when '--image-path'
79                                image_dir = arg
80                        when '--image-url'
81                                image_url = arg
82                        when '--image-format'
83                                image_format = arg
84                        when '--use-subject'
85                                use_subject = true
86                        end
87                end
88        rescue
89                raise usage
90        end
91        raise usage if (image_dir and not image_url) or (not image_dir and image_url)
92        image_dir.sub!( %r[/*$], '/' ) if image_dir
93        image_url.sub!( %r[/*$], '/' ) if image_url
94        url = ARGV.shift
95        if %r|http://([^:/]*):?(\d*)(/.*)| =~ url then
96                host = $1
97                port = $2.to_i
98                cgi = $3
99                raise 'bad url.' if not host or not cgi
100                port = 80 if port == 0
101        else
102                raise 'bad url.'
103        end
104
105        user = ARGV.shift
106        pass = ARGV.shift
107
108        require 'base64'
109        require 'nkf'
110        image_name = nil
111
112        mail = NKF::nkf( '-m0 -Xed', ARGF.read )
113        raise "#{File::basename __FILE__}: no mail text." if not mail or mail.length == 0
114
115        head, body = mail.split( /(?:\r?\n){2}, 2 )
116
117        if head =~ /Content-Type:\s*Multipart\/Mixed.*boundary=\"(.*?)\"/im then
118                if not image_dir or not image_url then
119                        raise "no --image-path and --image-url options"
120                end
121
122                bound = "--" + $1
123                body_sub = body.split( Regexp.compile( Regexp.escape( bound ) ) )
124                body_sub.each do |b|
125                        sub_head, sub_body = b.split( /(?:\r?\n){2}/, 2 )
126
127                        next unless sub_head =~ /Content-Type:/i
128
129                        if sub_head =~ %r[^Content-Type:\s*text/plain]i then
130                                @body = sub_body
131                        elsif sub_head =~ %r[
132                                ^Content-Type:\s*
133                                (?:image/ | application/octet-stream).+
134                                name=".+(\.[^.]+?)" (?# 1: extension)
135                        ]imx
136                                image_ext  = $1.downcase
137                                now        = Time::now
138                                list       = image_list( now.strftime( "%Y%m%d" ), image_dir )
139                                image_name = now.strftime( "%Y%m%d" ) + "_" + list.length.to_s + image_ext
140                                File::umask( 022 )
141                                open( image_dir + image_name, "wb" ) do |s|
142                                        begin
143                                                s.print Base64::decode64( sub_body.strip )
144                                        rescue NameError
145                                                s.print decode64( sub_body.strip )
146                                        end
147                                end
148                                if /\.bmp$/i =~ image_name then
149                                        bmp_to_png( image_dir + image_name )
150                                        image_name.sub!( /\.bmp$/i, '.png' )
151                                end
152                                @image_name ||= []
153                                @image_name << image_name
154                        end
155                end
156        elsif head =~ /^Content-Type:\s*text\/plain/i
157                @body = body
158        else
159                raise "cannot read this mail"
160        end
161
162        if @image_name then
163                img_src = ""
164                @image_name.each do |i|
165                        serial = i.sub( /^\d+_(\d+)\./n, '\1' )
166                        img_src += image_format.gsub( /\$0/, serial ).gsub( /\$1/, image_url + i )
167                end
168                if use_subject then
169                        @body = "#{img_src}\n#{@body}".sub( /(?:\r?\n|\r)+\z/, "\n" )
170                else
171                        @body = "#{@body}".sub( /(?:\r?\n|\r)+\z/, "\n" ) << img_src
172                end
173        end
174
175        addr = nil
176        if /^To:(.*)$/ =~ head then
177                addr = case to = $1.strip
178                when /.*?\s*<(.+)>/
179                when /(.+?)\s*\(.*\)/
180                        $1
181                else
182                        to
183                end
184        end
185
186        if /([^-]+)-(.*)@/ =~ addr then
187                user ||= $1
188                pass ||= $2
189        end
190
191        raise "no user." unless user
192        raise "no passwd." unless pass
193
194        subject = ''
195        nextline = false
196        headlines = head.split( /(?:\r?\n|\r)+/ )
197        for n in 0 .. headlines.size-1
198                if nextline then
199                        if /^[ \t]/ =~ headlines[n] then
200                                s = headlines[n].sub( /^[ \t]/, '' )
201                                subject += NKF::nkf( '-eXd', s )
202                        else
203                                break
204                        end
205                end
206                if /^Subject:\s*(.+)$/i =~ headlines[n] then
207                        subject = NKF::nkf( '-eXd', $1 )
208                        nextline = true
209                end
210        end
211        if use_subject then
212                title = ''
213                @body = "#{subject}\n#{@body}"
214        else
215                title = subject
216        end
217
218        require 'cgi'
219        require 'nkf'
220        data = "title=#{CGI::escape title}"
221        data << "&body=#{CGI::escape @body}"
222        data << "&append=true"
223
224        require 'net/http'
225        Net::HTTP.start( host, port ) do |http|
226                auth = ["#{user}:#{pass}"].pack( 'm' ).strip
227                res, = http.get( cgi, {
228                                'Authorization' => "Basic #{auth}",
229                                'Referer'       => url })
230                if %r|<input type="hidden" name="csrf_protection_key" value="([^"]+)">| =~ res.body then
231                        data << "&csrf_protection_key=#{CGI::escape( CGI::unescapeHTML( $1 ) )}"
232                end
233                res, = http.post( cgi, data, {
234                                'Authorization' => "Basic #{auth}",
235                                'Referer'       => url })
236        end
237
238rescue
239        $stderr.puts $!
240        $stderr.puts $@.join( "\n" )
241        File::delete( image_dir + image_name ) if image_dir and image_name and FileTest::exist?( image_dir + image_name )
242        exit 1
243end
Note: See TracBrowser for help on using the browser.