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

Revision 7072, 6.1 kB (checked in by sho, 6 years ago)

platform/tdiary/util/posttdiary/posttdiary.rb: fixed error when no body text in the mail.

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 = <<-TEXT
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
30  text.gsub( /\t/, '' )
31end
32
33def image_list( date, path )
34        image_path = []
35        Dir.foreach( path ) do |file|
36                if file =~ /(\d{8,})_(\d+)\.(.*)/ then
37                        if $1 == date then
38                                image_path[$2.to_i] = file
39                        end
40                end
41        end
42        image_path
43end
44
45def bmp_to_png( bmp )
46        png = bmp.sub( /\.bmp$/, '.png' )
47        begin
48                require 'magick'
49                img = Magick::Image::new( bmp )
50                img.write( 'magick' => 'png', 'filename' => png )
51        rescue LoadError
52                system( "convert #{bmp} #{png}" )
53        end
54        if FileTest::exist?( png )
55                File::delete( bmp )
56                png
57        else
58                bmp
59        end
60end
61
62begin
63
64        raise usage if ARGV.length < 1
65
66        require 'getoptlong'
67        parser = GetoptLong::new
68        image_dir = nil
69        image_url = nil
70        image_format = ' <img class="photo" src="$1" alt="">'
71        use_subject = false
72        parser.set_options(
73                ['--image-path', '-i', GetoptLong::REQUIRED_ARGUMENT],
74                ['--image-url', '-u', GetoptLong::REQUIRED_ARGUMENT],
75                ['--image-format', '-f', GetoptLong::REQUIRED_ARGUMENT],
76                ['--use-subject', '-s', GetoptLong::NO_ARGUMENT]
77        )
78        begin
79                parser.each do |opt, arg|
80                        case opt
81                        when '--image-path'
82                                image_dir = arg
83                        when '--image-url'
84                                image_url = arg
85                        when '--image-format'
86                                image_format = arg
87                        when '--use-subject'
88                                use_subject = true
89                        end
90                end
91        rescue
92                raise usage
93        end
94        raise usage if (image_dir and not image_url) or (not image_dir and image_url)
95        if image_dir then
96                image_dir += '/' unless %r[/$] =~ image_dir
97        end
98        if image_url then
99                image_url += '/' unless %r[/$] =~ image_url
100        end
101        url = ARGV.shift
102        if %r|http://([^:/]*):?(\d*)(/.*)| =~ url then
103                host = $1
104                port = $2.to_i
105                cgi = $3
106                raise 'bad url.' if not host or not cgi
107                port = 80 if port == 0
108        else
109                raise 'bad url.'
110        end
111       
112        user = ARGV.shift
113        pass = ARGV.shift
114
115        require 'base64'
116        require 'nkf'
117        image_name = nil
118
119        mail = NKF::nkf( '-m0 -Xed', ARGF.read )
120        raise "#{File::basename __FILE__}: no mail text." if not mail or mail.length == 0
121       
122        head, body = mail.split( /\r*\n\r*\n/, 2 )
123
124        if head =~ /Content-Type:\s*Multipart\/Mixed.*boundary=\"(.*?)\"/im then
125                if not image_dir or not image_url then
126                        raise "no --image-path and --image-url options"
127                end
128       
129                bound = "--" + $1
130                body_sub = body.split( Regexp.compile( Regexp.escape( bound ) ) )
131                body_sub.each do |b|
132                        sub_head, sub_body = b.split( /\r*\n\r*\n/, 2 )
133
134                        next unless sub_head =~ /Content-Type/
135
136                        if sub_head =~ %r[^Content-Type:\s*text/plain]i then
137                                @body = sub_body
138                        elsif sub_head =~ %r[^Content-Type:\s*(image/|application/octet-stream).*name=".*(\..*?)"]im
139                                image_ext = $2.downcase
140                                now = Time::now
141                                list = image_list( now.strftime( "%Y%m%d" ), image_dir )
142                                image_name = now.strftime( "%Y%m%d" ) + "_" + list.length.to_s + image_ext
143                                File::umask( 022 )
144                                open( image_dir + image_name, "wb" ) do |s|
145                                        begin
146                                                s.print Base64::decode64( sub_body.strip )
147                                        rescue NameError
148                                                s.print decode64( sub_body.strip )
149                                        end
150                                end
151                                if /\.bmp$/i =~ image_name then
152                                        bmp_to_png( image_dir + image_name )
153                                        image_name.sub!( /\.bmp$/, '.png' )
154                                end
155                                @image_name = [] unless @image_name
156                                @image_name << image_name
157                        end
158                end
159        elsif head =~ /^Content-Type:\s*text\/plain/i
160                @body = body
161        else
162                raise "cannot read this mail"
163        end
164
165        if @image_name then
166                img_src = ""
167                @image_name.each do |i|
168                        serial = i.sub( /^\d+_(\d+)\..*$/, '\1' )
169                        img_src += image_format.gsub( /\$0/, serial ).gsub( /\$1/, image_url + i )
170                end
171                if use_subject then
172                        @body = "#{img_src}\n#{(@body || '').sub( /\n+\z/, '' )}"
173                else
174                        @body = "#{(@body || '').sub( /\n+\z/, '' )}\n#{img_src}"
175                end
176        end
177
178        addr = nil
179        if /^To:(.*)$/ =~ head then
180                to = $1.strip
181                if /.*?\s*<(.*)>/ =~ to then
182                        addr = $1
183                elsif /(.*?)\s*\(.*\)/ =~ to
184                        addr = $1
185                else
186                        addr = to
187                end
188        end
189       
190        if /([^-]+)-(.*)@/ =~ addr then
191                user = $1 unless user
192                pass = $2 unless pass
193        end
194       
195        raise "no user." unless user
196        raise "no passwd." unless pass
197       
198        subject = ''
199        nextline = false
200        headlines = head.split( /[\r\n]+/ )
201        for n in 0 .. headlines.size-1
202                if nextline then
203                        if /^[ \t]/ =~ headlines[n] then
204                                s = headlines[n].sub( /^[ \t]/, '' )
205                                subject += NKF::nkf( '-eXd', s )
206                        else
207                                break
208                        end
209                end
210                if /^Subject:(.*)$/ =~ headlines[n] then
211                        s = $1.sub( /^\s+/, '' )
212                        subject = NKF::nkf( '-eXd', s )
213                        nextline = true
214                end
215        end
216        if use_subject then
217                title = ''
218                @body = "#{subject}\n#{@body}"
219        else
220                title = subject
221        end
222
223        require 'cgi'
224        require 'nkf'
225        data = "title=#{CGI::escape title}"
226        data << "&body=#{CGI::escape @body}"
227        data << "&append=true"
228
229        require 'net/http'
230        Net::HTTP.start( host, port ) do |http|
231                auth = ["#{user}:#{pass}"].pack( 'm' ).strip
232                res, = http.get( cgi,
233                                'Authorization' => "Basic #{auth}",
234                                'Referer' => url )
235                if %r|<input type="hidden" name="csrf_protection_key" value="([^"]+)">| =~ res.body then
236                        data << "&csrf_protection_key=#{CGI::escape( CGI::unescapeHTML( $1 ) )}"
237                end
238                res, = http.post( cgi, data,
239                                'Authorization' => "Basic #{auth}",
240                                'Referer' => url )
241        end
242
243rescue
244        $stderr.puts $!
245        $stderr.puts $@.join( "\n" )
246        File::delete( image_dir + image_name ) if image_dir and image_name and FileTest::exist?( image_dir + image_name )
247        exit 1
248end
Note: See TracBrowser for help on using the browser.