tdiary 4.0.2.20140201 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/ChangeLog +3 -0
  4. data/Gemfile +5 -5
  5. data/Gemfile.lock +48 -29
  6. data/README.md +1 -1
  7. data/Rakefile +1 -1
  8. data/index.rb +2 -2
  9. data/js/01conf.js +16 -0
  10. data/misc/convert2.rb +3 -3
  11. data/misc/filter/limitdays.rb +2 -2
  12. data/misc/filter/linkcheck.rb +2 -2
  13. data/misc/lib/fcgi_patch.rb +3 -3
  14. data/misc/paas/cloudfoundry/Gemfile.lock +51 -48
  15. data/misc/paas/heroku/Gemfile.lock +23 -21
  16. data/misc/paas/sqale/Gemfile.lock +23 -21
  17. data/misc/plugin/a.rb +4 -4
  18. data/misc/plugin/calendar2.rb +1 -1
  19. data/misc/plugin/category.rb +3 -3
  20. data/misc/plugin/comment_emoji_autocomplete.rb +1 -1
  21. data/misc/plugin/comment_mail-qmail.rb +1 -1
  22. data/misc/plugin/comment_mail-sendmail.rb +1 -1
  23. data/misc/plugin/comment_mail-smtp.rb +1 -1
  24. data/misc/plugin/counter.rb +27 -27
  25. data/misc/plugin/disp_referrer.rb +1 -1
  26. data/misc/plugin/en/amazon.rb +2 -2
  27. data/misc/plugin/en/category.rb +1 -1
  28. data/misc/plugin/en/counter.rb +1 -1
  29. data/misc/plugin/en/disp_referrer.rb +1 -1
  30. data/misc/plugin/en/kw.rb +1 -1
  31. data/misc/plugin/en/search_form.rb +1 -1
  32. data/misc/plugin/en/todo.rb +1 -1
  33. data/misc/plugin/en/weather.rb +5 -2
  34. data/misc/plugin/image.rb +2 -2
  35. data/misc/plugin/ja/disp_referrer.rb +7 -7
  36. data/misc/plugin/ja/my-sequel.rb +1 -1
  37. data/misc/plugin/ja/recent_comment3.rb +1 -1
  38. data/misc/plugin/ja/referer_scheme.rb +1 -1
  39. data/misc/plugin/ja/search_control.rb +1 -1
  40. data/misc/plugin/ja/search_form.rb +2 -2
  41. data/misc/plugin/ja/todo.rb +1 -1
  42. data/misc/plugin/ja/weather.rb +17 -12
  43. data/misc/plugin/makelirs.rb +4 -4
  44. data/misc/plugin/my-ex.rb +1 -1
  45. data/misc/plugin/my-sequel.rb +1 -1
  46. data/misc/plugin/pb-show.rb +1 -1
  47. data/misc/plugin/recent_comment.rb +5 -5
  48. data/misc/plugin/recent_comment3.rb +2 -2
  49. data/misc/plugin/recent_namazu.rb +4 -4
  50. data/misc/plugin/recent_rss.rb +7 -7
  51. data/misc/plugin/referer_scheme.rb +2 -2
  52. data/misc/plugin/search-default.rb +1 -1
  53. data/misc/plugin/sn.rb +3 -3
  54. data/misc/plugin/speed_comment.rb +1 -1
  55. data/misc/plugin/squeeze.rb +8 -8
  56. data/misc/plugin/tb-show.rb +1 -1
  57. data/misc/plugin/theme_online.rb +25 -0
  58. data/misc/plugin/tlink.rb +2 -2
  59. data/misc/plugin/todo.rb +2 -2
  60. data/misc/plugin/weather.rb +82 -26
  61. data/misc/plugin/whatsnew.rb +1 -1
  62. data/misc/plugin/xmlrpc/xmlrpc.rb +11 -11
  63. data/misc/theme_convert/theme_convert.rb +3 -3
  64. data/plugin/00default.rb +35 -28
  65. data/plugin/50sp.rb +1 -1
  66. data/plugin/60sf.rb +1 -1
  67. data/plugin/90migrate.rb +2 -2
  68. data/plugin/en/00default.rb +1 -1
  69. data/plugin/ja/00default.rb +1 -1
  70. data/spec/acceptance/append_comment_spec.rb +18 -18
  71. data/spec/acceptance/append_diary_spec.rb +22 -22
  72. data/spec/acceptance/bugfix/encoding_error_spec.rb +1 -1
  73. data/spec/acceptance/save_conf_comment_spec.rb +15 -15
  74. data/spec/acceptance/save_conf_default_spec.rb +26 -26
  75. data/spec/acceptance/save_conf_dnsbl_spec.rb +19 -19
  76. data/spec/acceptance/save_conf_filter_spec.rb +6 -6
  77. data/spec/acceptance/save_conf_plugin_spec.rb +11 -11
  78. data/spec/acceptance/save_conf_referer_spec.rb +4 -4
  79. data/spec/acceptance/save_conf_security_spec.rb +28 -28
  80. data/spec/acceptance/update_diary_spec.rb +16 -16
  81. data/spec/acceptance/view_category_spec.rb +1 -1
  82. data/spec/acceptance/view_comment_spec.rb +6 -6
  83. data/spec/acceptance/view_diary_spec.rb +25 -25
  84. data/spec/acceptance/view_referer_spec.rb +3 -3
  85. data/spec/core/compatible_spec.rb +5 -5
  86. data/spec/core/configuration_spec.rb +3 -3
  87. data/spec/core/core_ext_spec.rb +7 -7
  88. data/spec/core/io/default_spec.rb +1 -1
  89. data/spec/core/plugin_spec.rb +41 -41
  90. data/spec/core/rack/assets/precompile_spec.rb +3 -3
  91. data/spec/core/rack/html_anchor_spec.rb +15 -15
  92. data/spec/core/rack/static_spec.rb +3 -3
  93. data/spec/core/rack/valid_request_path_spec.rb +13 -13
  94. data/spec/core/style/tdiary_style_spec.rb +10 -10
  95. data/spec/core/style/wiki_style_spec.rb +16 -16
  96. data/spec/plugin/bq_spec.rb +2 -2
  97. data/spec/spec_helper.rb +3 -1
  98. data/tdiary/configuration.rb +2 -2
  99. data/tdiary/environment.rb +1 -1
  100. data/tdiary/io/default.rb +1 -1
  101. data/tdiary/lang/ja.rb +2 -2
  102. data/tdiary/tasks/db.rake +5 -5
  103. data/tdiary/version.rb +1 -1
  104. data/test/disp_referrer_test.rb +4 -4
  105. data/test/my-sequel_test.rb +1 -1
  106. data/test/test_plugin_helper.rb +47 -0
  107. data/test/weather-ADDS-METARS-PHTO-140131.html +109 -0
  108. data/test/weather-ADDS-METARS-RJAA-130131.html +111 -0
  109. data/test/weather-ADDS-METARS-RJAA-130227.html +111 -0
  110. data/test/weather_test.rb +144 -18
  111. data/update.rb +2 -2
  112. metadata +10 -3
@@ -36,7 +36,7 @@ module ::TDiary
36
36
  yield com,i
37
37
  end
38
38
  end
39
-
39
+
40
40
  def each_visible_pingback_tail( limit = 3 )
41
41
  i = 0
42
42
  @comments.find_all {|com|
@@ -22,7 +22,7 @@ def recent_comment( ob_max = 'OBSOLUTE', sep = 'OBSOLUTE', ob_form = 'OBSOLUTE',
22
22
  recent_comment_init
23
23
 
24
24
  max = @conf['recent_comment.max']
25
- form = @conf['recent_comment.date_format']
25
+ form = @conf['recent_comment.date_format']
26
26
  except = @conf['recent_comment.except_list']
27
27
  format = @conf['recent_comment.format']
28
28
  notfound_msg = @conf['recent_comment.notfound_msg']
@@ -34,7 +34,7 @@ def recent_comment( ob_max = 'OBSOLUTE', sep = 'OBSOLUTE', ob_form = 'OBSOLUTE',
34
34
  @diaries.each_value do |diary|
35
35
  next unless diary.visible?
36
36
  diary.each_comment_tail( max ) do |comment, idx|
37
- if (except != '') && (/#{except}/ =~ comment.name)
37
+ if (except != '') && (/#{except}/ =~ comment.name)
38
38
  next
39
39
  end
40
40
  comments << comment
@@ -42,9 +42,9 @@ def recent_comment( ob_max = 'OBSOLUTE', sep = 'OBSOLUTE', ob_form = 'OBSOLUTE',
42
42
  index[comment.date] = idx
43
43
  end
44
44
  end
45
-
45
+
46
46
  result = []
47
-
47
+
48
48
  comments.sort{|a,b| (a.date)<=>(b.date)}.reverse.each_with_index do |com,idx|
49
49
  break if idx >= max
50
50
  a = h(@index) + anchor("#{date[com.date].strftime( '%Y%m%d' )}#c#{'%02d' % index[com.date]}")
@@ -56,7 +56,7 @@ def recent_comment( ob_max = 'OBSOLUTE', sep = 'OBSOLUTE', ob_form = 'OBSOLUTE',
56
56
  result << recent_comment_format(format, idx, a, popup, str, date_str)
57
57
  result << "</li>\n"
58
58
  end
59
-
59
+
60
60
  if result.size == 0
61
61
  notfound_msg
62
62
  else
@@ -18,7 +18,7 @@ end
18
18
 
19
19
  def migrate_old_data
20
20
  # backward compatibility
21
- if File.exists?("#{@cache_path}/recent_comments") && !File.exists?("{#{@conf.data_path}/recent_comments")
21
+ if File.exist?("#{@cache_path}/recent_comments") && !File.exist?("{#{@conf.data_path}/recent_comments")
22
22
  FileUtils.mv( "#{@cache_path}/recent_comments", "#{@conf.data_path}/recent_comments" )
23
23
  end
24
24
  # workaround for "/foo//bar" doesn't equal "/foo/bar"
@@ -47,7 +47,7 @@ def recent_comment3(ob_max = 'OBSOLUTE' ,sep = 'OBSOLUTE',ob_date_format = 'OBSO
47
47
  recent_comment3_init
48
48
 
49
49
  cache = @conf['recent_comment3.cache'].untaint
50
- date_format = @conf['recent_comment3.date_format']
50
+ date_format = @conf['recent_comment3.date_format']
51
51
  excepts = @conf['recent_comment3.except_list'].split(/,/)
52
52
  format = @conf['recent_comment3.format']
53
53
  titlelen = @conf['recent_comment3.titlelen']
@@ -5,11 +5,11 @@
5
5
  # namazi.cgiが作成する検索キーワードログ(NMZ.slog)から
6
6
  # 最新xx件分の検索語を表示します。
7
7
  # パラメタ:
8
- # file: 検索キーワードログファイル名(絶対パス表記)
9
- # namazu: なまずcgi名
10
- # limit: 表示件数(未指定時:5)
8
+ # file: 検索キーワードログファイル名(絶対パス表記)
9
+ # namazu: なまずcgi名
10
+ # limit: 表示件数(未指定時:5)
11
11
  # sep: セパレータ(未指定時:空白)
12
- # make_link: <a>を生成するか?(未指定時:生成する)
12
+ # make_link: <a>を生成するか?(未指定時:生成する)
13
13
  #
14
14
  #
15
15
  # Copyright (c) 2002 Hiroyuki Ikezoe <zoe@kasumi.sakura.ne.jp>
@@ -1,5 +1,5 @@
1
1
  # -*- indent-tabs-mode: t -*-
2
- # recent_rss.rb: RSS recent plugin
2
+ # recent_rss.rb: RSS recent plugin
3
3
  #
4
4
  # options:
5
5
  # @options['recent_rss.use-image-link'] : use image as link
@@ -35,13 +35,13 @@ def recent_rss( url, max = 5, cache_time = 3600, show_modified = true )
35
35
  cache_file = "#{@cache_path}/recent_rss.#{CGI.escape(url)}"
36
36
 
37
37
  recent_rss_cache_rss(url, cache_file, cache_time.to_i)
38
-
38
+
39
39
  return '' unless test(?r, cache_file)
40
40
 
41
41
  rv = %Q|<div class="recent-rss">\n|
42
42
 
43
43
  site_info, *infos = recent_rss_read_from_cache(cache_file)
44
-
44
+
45
45
  if site_info
46
46
  title, url, time, image = site_info
47
47
  content = recent_rss_entry_to_html( title, url, time, image, show_modified )
@@ -49,9 +49,9 @@ def recent_rss( url, max = 5, cache_time = 3600, show_modified = true )
49
49
  rv << %Q|<span class="#{recent_rss_modified_class(time)}">#{content}</span>\n|
50
50
  rv << "</div>\n"
51
51
  end
52
-
52
+
53
53
  have_entry = infos.size > 0 && max > 0
54
-
54
+
55
55
  rv << %Q|<ol class="recent-rss">\n| if have_entry
56
56
  i = 0
57
57
  infos.each do |title, url, time, image|
@@ -93,14 +93,14 @@ def recent_rss_cache_rss(url, cache_file, cache_time)
93
93
  cached_time = File.mtime(cache_file) if File.exist?(cache_file)
94
94
 
95
95
  if cached_time.nil? or Time.now > cached_time + cache_time
96
-
96
+
97
97
  begin
98
98
  uri = URI.parse(url)
99
99
 
100
100
  raise URI::InvalidURIError unless uri.is_a?(URI::HTTP)
101
101
 
102
102
  rss_source = recent_rss_fetch_rss(uri, cached_time)
103
-
103
+
104
104
  raise InvalidResourceError if rss_source.nil?
105
105
 
106
106
  # parse RSS
@@ -30,12 +30,12 @@ end
30
30
 
31
31
  unless @conf.referer_table.respond_to?( 'scheme_tdiary', true ) then
32
32
  class << @conf.referer_table
33
- TdiaryDates = [
33
+ TdiaryDates = [
34
34
  ['(?:\\?date=)?(\d{4})(\d{2})(\d{2})-(\d+)(?:\.html)?.*', '(\1-\2-\3~)'],
35
35
  ['(?:\\?date=)?(\d{4})(\d{2})(\d{2})(?:\.html)?.*', '(\1-\2-\3)'],
36
36
  ['(?:\\?date=)?(\d{4})(\d{2})(?:\.html)?.*', '(\1-\2)'],
37
37
  ['(?:\\?date=)?(\d{2})(\d{2})(?:\.html)?.*', '(\1-\2)'],
38
- ]
38
+ ]
39
39
  private
40
40
  def scheme_tdiary( url, name )
41
41
  TdiaryDates.each do |a|
@@ -233,7 +233,7 @@ end
233
233
 
234
234
  def search_result
235
235
  unless @conf.io_class == (TDiary.const_defined?('DefaultIO') ? TDiary::DefaultIO : TDiary::IO::Default)
236
- return %Q|<p class="message">could not use this plugin under #{@conf.io_class}.</p>|
236
+ return %Q|<p class="message">could not use this plugin under #{@conf.io_class}.</p>|
237
237
  end
238
238
 
239
239
  query = CGI::unescape( @cgi.params['q'][0] )
data/misc/plugin/sn.rb CHANGED
@@ -62,13 +62,13 @@
62
62
  * first version
63
63
  =end
64
64
 
65
- add_body_enter_proc do |date|
65
+ add_body_enter_proc do |date|
66
66
  @sn_count = 1
67
67
  @sn_idx = 0
68
68
  ""
69
69
  end
70
70
 
71
- add_body_leave_proc do |date|
71
+ add_body_leave_proc do |date|
72
72
  @sn_count = 1
73
73
  @sn_idx = 0
74
74
  ""
@@ -94,7 +94,7 @@ def sn( number = nil )
94
94
  @sn_count += 1
95
95
  %Q[#{'%d' % number}]
96
96
  end
97
-
97
+
98
98
  def sn_anchorid
99
99
  %Q[#{'%d' % @sn_idx}]
100
100
  end
@@ -13,7 +13,7 @@
13
13
  * support conf_proc.
14
14
 
15
15
  2002-03-24 TADA Tadashi <sho@spc.gr.jp>
16
- * suppress output in mobile mode.
16
+ * suppress output in mobile mode.
17
17
 
18
18
  2002-03-12 TADA Tadashi <sho@spc.gr.jp>
19
19
  * support insert into @header.
@@ -5,13 +5,13 @@
5
5
  # Create daily HTML file from tDiary database.
6
6
  #
7
7
  # See URLs below for more details.
8
- # http://ponx.s5.xrea.com/hiki/squeeze.rb.html (English)
9
- # http://ponx.s5.xrea.com/hiki/ja/squeeze.rb.html (Japanese)
8
+ # http://ponx.s5.xrea.com/hiki/squeeze.rb.html (English)
9
+ # http://ponx.s5.xrea.com/hiki/ja/squeeze.rb.html (Japanese)
10
10
  #
11
11
  # Copyright (C) 2002 MUTOH Masao <mutoh@highway.ne.jp>
12
12
  # You can redistribute it and/or modify it under GPL2.
13
13
  #
14
- # The original version of this file was distributed with squeeze
14
+ # The original version of this file was distributed with squeeze
15
15
  # TADA Tadashi <sho@spc.gr.jp> with GPL2.
16
16
  #
17
17
  unless $tdiary_squeeze_loaded
@@ -77,7 +77,7 @@ if mode == "CMD" || mode == "CGI"
77
77
  $:.unshift tdiary_path
78
78
  else
79
79
  @options = Hash.new
80
- File::readlines("tdiary.conf").each {|item|
80
+ File::readlines("tdiary.conf").each {|item|
81
81
  if item =~ /@options/
82
82
  begin
83
83
  eval(item)
@@ -114,7 +114,7 @@ module ::TDiary
114
114
  class YATDiarySqueeze < TDiaryBase
115
115
  def initialize(diary, dest, all_data, overwrite, compat, conf, suffix)
116
116
  @ignore_parser_cache = true
117
-
117
+
118
118
  cgi = CGI::new
119
119
  def cgi.referer; nil; end
120
120
  def cgi.user_agent; 'bot'; end
@@ -128,7 +128,7 @@ module ::TDiary
128
128
  @compat = compat
129
129
  @suffix = suffix
130
130
  end
131
-
131
+
132
132
  def execute
133
133
  if @compat
134
134
  dir = @dest
@@ -143,7 +143,7 @@ module ::TDiary
143
143
  File::delete( filename )
144
144
  end
145
145
  if @diary.visible? or @all_data
146
- if not FileTest::exist?(filename) or
146
+ if not FileTest::exist?(filename) or
147
147
  File::mtime(filename) != @diary.last_modified
148
148
  File::open(filename, 'w'){|f| f.write(eval_rhtml)}
149
149
  File::utime(@diary.last_modified, @diary.last_modified, filename)
@@ -158,7 +158,7 @@ module ::TDiary
158
158
  end
159
159
  name
160
160
  end
161
-
161
+
162
162
  protected
163
163
  def mode
164
164
  'day'
@@ -26,7 +26,7 @@
26
26
  # %Q|#{comment_new_tb_backup }</a>]<br>[TrackBack to <a href="#{@tb_url}">#{@tb_url}|
27
27
  # end
28
28
  #
29
-
29
+
30
30
  # running on only non mobile mode
31
31
  unless @cgi.mobile_agent? then
32
32
 
@@ -0,0 +1,25 @@
1
+ # theme_online.rb: choice theme from online repository on tDiary.org
2
+ #
3
+ # Copyright (C) 2014 by TADA Tadashi <t@tdtds.jp>
4
+ # You can distribute and/or modify it under GPL
5
+ #
6
+ require 'json'
7
+ require 'open-uri'
8
+
9
+ def theme_list_online(list)
10
+ begin
11
+ online_list = JSON.load(open('http://theme.tdiary.org/themes.json', &:read))['themes']
12
+ list + online_list.keys.map do |t|
13
+ title = online_list[t]['title']
14
+ label = t == title ? '' : " (#{title})"
15
+ ["online/#{t}", "#{t}#{label}"]
16
+ end
17
+ rescue
18
+ @logger.error "could not get theme list from online: #$!"
19
+ list
20
+ end
21
+ end
22
+
23
+ def theme_url_online(theme)
24
+ "http://theme.tdiary.org/#{h theme}/#{h theme}.css"
25
+ end
data/misc/plugin/tlink.rb CHANGED
@@ -41,7 +41,7 @@
41
41
 
42
42
  2002-05-16 MUTOH Masao <mutoh@highway.ne.jp>
43
43
  * cache mechanism support.
44
- * code cleanup(remove require 'cgi',
44
+ * code cleanup(remove require 'cgi',
45
45
  getcomment rename to tlink_getcomment).
46
46
 
47
47
  2002-05-05 NT <nt@24i.net>
@@ -70,7 +70,7 @@ require 'net/http'
70
70
  require 'kconv'
71
71
  require 'pstore'
72
72
 
73
- def tlink_initialize
73
+ def tlink_initialize
74
74
  dir = @cache_path + "/tlink"
75
75
  @tlink_path = dir + "/tlink.dat"
76
76
 
data/misc/plugin/todo.rb CHANGED
@@ -34,7 +34,7 @@
34
34
  #
35
35
  # Copyright (c) 2001,2002,2003 Junichiro KITA <kita@kitaj.no-ip.com>
36
36
  # Distributed under the GPL
37
- #
37
+ #
38
38
 
39
39
  require 'fileutils'
40
40
  require 'time'
@@ -146,7 +146,7 @@ end
146
146
 
147
147
  # backward compatibility
148
148
  def todo_file
149
- if File.exists?( "#{@cache_path}/todo" ) then
149
+ if File.exist?( "#{@cache_path}/todo" ) then
150
150
  FileUtils.mv( "#{@cache_path}/todo", "#{@conf.data_path}/todo")
151
151
  end
152
152
  (@options && @options['todo.path'] || @conf.data_path) + "/todo"
@@ -68,9 +68,17 @@ of GPL version 2 or later.
68
68
  require 'net/http'
69
69
  require 'cgi'
70
70
  require 'timeout'
71
+ require 'date' # DateTime.strptime
71
72
 
72
73
  =begin
73
74
  == Classes and methods
75
+ === WeatherParser
76
+
77
+ --- WeatherParser::parse
78
+ =end
79
+
80
+
81
+ =begin
74
82
  === WeatherTranslator module
75
83
  We want Japanese displayed in a diary written in Japanese.
76
84
 
@@ -144,45 +152,61 @@ class Weather
144
152
  # magic numbers
145
153
  WAITTIME = 10
146
154
  MAXREDIRECT = 10
155
+ AVIATIONWEATHER_STATION_REGEXP = %r|(?:aviationweather.gov/adds/metars/\?.*station_ids=)([A-Z]{4,4})\b|
156
+ NOAA_STATION_REGEXP = %r|(?:weather.noaa.gov/weather/current/)([A-Z]{4,4})\b|
157
+ RAW_STATION_REGEXP = %r|\A([A-Z]{4,4})\z|
158
+ STATION_URL_TEMPLATE = "http://www.aviationweather.gov/adds/metars/?station_ids=%s&std_trans=translated&chk_metars=on&hoursStr=most+recent+only"
159
+
160
+ def Weather::extract_station_id(url)
161
+ [AVIATIONWEATHER_STATION_REGEXP, NOAA_STATION_REGEXP, RAW_STATION_REGEXP].each do |r|
162
+ m = r.match(url)
163
+ return m[1] if m and m[1]
164
+ end
165
+ return nil
166
+ end
147
167
 
148
168
  # edit this method according to the HTML we will get
149
169
  def parse_html( html, items )
150
170
  htmlitems = Hash.new
151
171
 
152
- # weather data is in the 4th table in the HTML from weather.noaa.gov
153
- table = html.scan( %r[<table.*?>(.*?)</table>]mi )[3][0]
154
- table.scan( %r[<tr.*?>(.*?)</tr>]mi ).collect {|a| a[0]}.each do |row|
172
+ # weather data is in the 1st table in the HTML from aviationweather.gov
173
+ table = html.scan( %r[<table.*?>(.*?)</table>]mi )
174
+ return if not table or not table[0] or not table[0][0]
175
+ table[0][0].scan( %r[<tr.*?>(.*?)</tr>]mi ).collect {|a| a[0]}.each do |row|
155
176
  # <tr><td> *item* -> downcased </td><td> *value* </td></tr>
156
177
  if %r[<td.*?>(.*?)</td>\s*<td.*?>(.*?)</td>]mi =~ row then
157
178
  item = $1
158
179
  value = $2
159
- item = item.gsub( /<br>/i, '/' ).gsub( /<.*?>/m , '').strip.downcase
160
- value = value.gsub( /<br>/i, '/' ).gsub( /<.*?>/m , '').strip
180
+ item = item.gsub( /<br>/i, '/' ).gsub( /<.*?>/m , '').strip.sub(/:$/, '').downcase
181
+ value = value.gsub(/\&(nbsp|#160);/, ' ').gsub(/\&#46;/, '.').gsub(/\&#37/, '%').gsub(/\&deg;/, '').gsub( /<br>/i, '/' ).gsub( /<.*?>/m , '').strip
161
182
 
162
183
  # unit conversion settings
163
184
  units = []
164
185
  case item
165
186
  when 'conditions at'
166
187
  # we have to convert the UTC time into UNIX time
167
- if /(\d{4}).(\d\d).(\d\d)\s*(\d\d)(\d\d)\s*UTC$/ =~ value then
168
- value = Time::utc( $1, $2, $3, $4, $5 ).to_i.to_s
188
+ if /observed\s+(.*)$/ =~ value then
189
+ value = DateTime.strptime($1, "%H%M %z %d %B %Y").to_time.to_i.to_s
169
190
  else
170
191
  raise StandardError, 'Parse error in "Conditions at"'
171
192
  end
172
193
  when 'visibility' # we want to preserve adjective phrase if possible
173
- if /(.*)([\d.]+)\s*mile(\(s\))?/i =~ value then
174
- htmlitems["#{item}(km)"] = sprintf( '%s %.3f', $1.strip, $2.to_f * 1.610 )
175
- htmlitems["#{item}(mile)"] = sprintf( '%s %s', $1.strip, $2 )
194
+ if /(.+)miles?/i =~ value then
195
+ htmlitems["#{item}(mile)"] = $1.strip
196
+ end
197
+ if /([^\(]+)km/i =~ value then
198
+ htmlitems["#{item}(km)"] = $1.strip
199
+ end
200
+ when 'winds' # we want to preserve adjective phrase if possible
201
+ %w(MPH knots m/s).each do |unit|
202
+ speed = value.scan( /([\d.]+)\s*#{unit}/i ).collect { |x| x[0] }
203
+ htmlitems["wind(#{unit})"] = speed.join(',')
176
204
  end
177
- when 'wind' # we want to preserve adjective phrase if possible
178
- speed = value.scan( /([\d.]+)\s*MPH/i ).collect { |x| x[0] }
179
- htmlitems["#{item}(MPH)"] = speed.join(',')
180
- htmlitems["#{item}(m/s)"] = speed.collect {|s| sprintf( '%.4f', s.to_f * 0.4472222 ) }.join(',')
181
205
  if /([\d.]+)\s*degrees?/i =~ value then
182
- htmlitems["#{item}(deg)"] = $1
206
+ htmlitems["wind(deg)"] = $1
183
207
  end
184
208
  if /from\s+(the\s+)?(\w+)/i =~ value then
185
- htmlitems["#{item}dir"] = $2 + ($3 ? " #{$3}" : '')
209
+ htmlitems["winddir"] = $2 + ($3 ? " #{$3}" : '')
186
210
  end
187
211
  if /(\(direction variable\))/i =~ value then
188
212
  htmlitems["#{item}dir"] << " #{$1}"
@@ -192,18 +216,19 @@ class Weather
192
216
  units = ['C', 'F']
193
217
  when 'windchill'
194
218
  units = ['C', 'F']
195
- when 'dew point'
219
+ when 'dewpoint'
196
220
  units = ['C', 'F']
197
221
  when 'relative humidity'
198
222
  units = ['%']
199
223
  when 'pressure (altimeter)'
200
- units = ['hPa']
224
+ units = ['mb'] # mb (mbar) and hPa results in same number
201
225
  end
202
226
 
203
227
  # parse the value with the units if preferred and possible
204
228
  units.each do |unit|
205
- if /(-?[\d.]+)\s*\(?#{unit}\b/i =~ value then
206
- htmlitems["#{item}(#{unit})"] = $1
229
+ if /(-?[\d.]+)\s*\D?\(?#{unit}\b/i =~ value then
230
+ number = $1
231
+ htmlitems["#{item}(#{unit})"] = number
207
232
  end
208
233
  end
209
234
 
@@ -213,6 +238,18 @@ class Weather
213
238
  end # if %r[<td.*?>(.*?)</td>\s*<td.*?>(.*?)</td>]mi =~ row
214
239
  end # table.scan( %r[<tr.*?>(.*?)</tr>]mi ) ... do |row|
215
240
 
241
+ # Obtain weather from Weather: or Clouds:
242
+ weather = 'Unknown'
243
+ # e.g.: FG -RA (fog, light rain)
244
+ if /\((.*)\)/ =~ htmlitems['weather'] then
245
+ weather = $1.strip
246
+ # e.g.: few clouds at 3000 feet AGL
247
+ elsif /(.*?)\s+at/ =~ htmlitems['clouds'] then
248
+ weather = $1.strip
249
+ end
250
+ # Weather seemed to have been slash divided capitalized string
251
+ htmlitems['weather'] = weather.split(/,\s*/).map{|e| e.strip.capitalize}.join('/')
252
+
216
253
  # translate the parsed HTML into the Weather hash with more generic key
217
254
  items.each do |from, to|
218
255
  if htmlitems[from] then
@@ -257,7 +294,7 @@ class Weather
257
294
  px_port = 80 if px_host and !px_port
258
295
  u = URI::parse( url )
259
296
  Net::HTTP::Proxy( px_host, px_port ).start( u.host, u.port ) do |http|
260
- case res = http.get( u.path, header )
297
+ case res = http.get( u.request_uri, header )
261
298
  when Net::HTTPSuccess
262
299
  res.body
263
300
  when Net::HTTPRedirection
@@ -406,9 +443,9 @@ Weather_default_items = {
406
443
  'visibility(km)' => 'visibility(km)',
407
444
  'temperature(C)' => 'temperature(C)',
408
445
  'windchill(C)' => 'windchill(C)',
409
- 'dew point(C)' => 'dewpoint(C)',
446
+ 'dewpoint(C)' => 'dewpoint(C)',
410
447
  'relative humidity(%)' => 'humidity(%)',
411
- 'pressure (altimeter)(hPa)' => 'pressure(hPa)',
448
+ 'pressure (altimeter)(mb)' => 'pressure(hPa)',
412
449
  }
413
450
 
414
451
  # shows weather
@@ -436,6 +473,7 @@ def get_weather
436
473
  w = Weather::restore( path, @date )
437
474
  if not w or w.error then
438
475
  items = @options['weather.items'] || Weather_default_items
476
+ update_weather_url( @options )
439
477
  w = Weather.new( @date, @options['weather.tz'], @conf )
440
478
  w.get( @options['weather.url'], @options['weather.header'] || {}, items )
441
479
  if @options.has_key?( 'weather.oldest' ) then
@@ -448,11 +486,28 @@ def get_weather
448
486
  end
449
487
  end
450
488
 
489
+ # Update URL of weather information
490
+ #
491
+ # Around April, 2012, NOAA chnaged the URL of the current weather from
492
+ # http://weather.noaa.gov/weather/current/#{station_id}.html
493
+ # to
494
+ # http://www.aviationweather.gov/adds/metars/?station_ids=#{station_id}&std_trans=translated&chk_metars=on&hoursStr=most+recent+only
495
+ def update_weather_url( hash )
496
+ if hash['weather.url'] and match = hash['weather.url'].scan(%r[\Ahttp://weather.noaa.gov/weather/current/(\w{4,4}).html\z])[0]
497
+ hash['weather.url'] = Weather::STATION_URL_TEMPLATE % match[0]
498
+ end
499
+ end
500
+
451
501
  # www configuration interface
452
502
  def configure_weather
453
503
  if( @mode == 'saveconf' ) then
454
504
  # weather.url
455
- @conf['weather.url'] = @cgi.params['weather.url'][0]
505
+ station = Weather::extract_station_id( @cgi.params['weather.url'][0] )
506
+ if station
507
+ @conf['weather.url'] = Weather::STATION_URL_TEMPLATE % station
508
+ else
509
+ @conf['weather.url'] = @cgi.params['weather.url'][0]
510
+ end
456
511
  # weather.tz
457
512
  tz = @cgi.params['weather.tz'][0]
458
513
  unless tz.empty? then # need more checks
@@ -469,6 +524,7 @@ def configure_weather
469
524
  end
470
525
  end
471
526
  end
527
+ update_weather_url( @conf )
472
528
  weather_configure_html( @conf )
473
529
  end
474
530
 
@@ -482,13 +538,13 @@ _END
482
538
  end
483
539
 
484
540
  if not feed? and not @options['weather.in_title'] then
485
- add_body_enter_proc do |date|
541
+ add_body_enter_proc do |date|
486
542
  weather( date )
487
543
  end
488
544
  end
489
545
 
490
546
  if not feed? and @options['weather.in_title'] then
491
- add_title_proc do |date, title|
547
+ add_title_proc do |date, title|
492
548
  title + weather( date, false )
493
549
  end
494
550
  end
@@ -83,7 +83,7 @@ add_footer_proc do
83
83
  'name' => 'tdiary_whats_new',
84
84
  'value' => [@whats_new[:this_time]],
85
85
  'path' => cookie_path,
86
- 'expires' => Time::now.gmtime + 90*24*60*60
86
+ 'expires' => Time::now.gmtime + 90*24*60*60
87
87
  })
88
88
  add_cookie(cookie)
89
89
  end
@@ -44,7 +44,7 @@ server.add_handler('blogger.newPost') do |appkey, blogid, username, password, co
44
44
  title,body = content.split(/\n/,2)
45
45
  index = diary.add_section(title, body)
46
46
  src = diary.to_src
47
-
47
+
48
48
  @cgi.params.delete 'date'
49
49
  @cgi.params['old'] = [postid]
50
50
  @cgi.params['hide'] = diary.visible? ? [] : ['true']
@@ -78,7 +78,7 @@ server.add_handler('blogger.editPost') do |appkey, postid, username, password, c
78
78
  index = index.to_i
79
79
  time = Time::local( year, month, day ) + 12*60*60
80
80
  diary = tdiary[time]
81
-
81
+
82
82
  src = ''
83
83
  i = 0
84
84
  diary.each_section {|sec|
@@ -90,7 +90,7 @@ server.add_handler('blogger.editPost') do |appkey, postid, username, password, c
90
90
  end
91
91
  src << sec.to_src
92
92
  }
93
-
93
+
94
94
  @cgi.params.delete 'date'
95
95
  @cgi.params['old'] = [postid[0,8]]
96
96
  @cgi.params['hide'] = diary.visible? ? [] : ['true']
@@ -123,10 +123,10 @@ server.add_handler('blogger.deletePost') do |appkey, postid, username, password|
123
123
  tdiary = ::TDiary::TDiaryDay::new( @cgi, "day.rhtml", @conf )
124
124
  time = Time::local( year, month, day ) + 12*60*60
125
125
  diary = tdiary[time]
126
-
126
+
127
127
  diary.delete_section(index)
128
128
  src = diary.to_src
129
-
129
+
130
130
  @cgi.params.delete 'date'
131
131
  @cgi.params['old'] = [postid[0,8]]
132
132
  @cgi.params['hide'] = diary.visible? ? [] : ['true']
@@ -216,10 +216,10 @@ server.add_handler('metaWeblog.newPost') do |blogid, username, password, content
216
216
  tdiary = ::TDiary::TDiaryDay::new( @cgi, "day.rhtml", @conf )
217
217
  time = Time::local( year, month, day ) + 12*60*60
218
218
  diary = tdiary[time] || tdiary.instance_variable_get(:@io).diary_factory(time, '', '', @conf.style)
219
-
219
+
220
220
  index = diary.add_section(content['title'], content['description'])
221
221
  src = diary.to_src
222
-
222
+
223
223
  @cgi.params.delete 'date'
224
224
  @cgi.params['old'] = [postid]
225
225
  @cgi.params['hide'] = diary.visible? ? [] : ['true']
@@ -250,7 +250,7 @@ server.add_handler('metaWeblog.editPost') do |postid, username, password, conten
250
250
  index = index.to_i
251
251
  time = Time::local( year, month, day ) + 12*60*60
252
252
  diary = tdiary[time]
253
-
253
+
254
254
  src = ''
255
255
  i = 0
256
256
  diary.each_section {|sec|
@@ -261,7 +261,7 @@ server.add_handler('metaWeblog.editPost') do |postid, username, password, conten
261
261
  end
262
262
  src << sec.to_src
263
263
  }
264
-
264
+
265
265
  @cgi.params.delete 'date'
266
266
  @cgi.params['old'] = [postid[0,8]]
267
267
  @cgi.params['hide'] = diary.visible? ? [] : ['true']
@@ -478,7 +478,7 @@ server.add_handler('mt.setPostCategories') do |postid, username, password, categ
478
478
  diary = tdiary[time]
479
479
 
480
480
  @cgi.params.delete 'date'
481
-
481
+
482
482
  src = ''
483
483
  i = 0
484
484
  diary.each_section {|sec|
@@ -494,7 +494,7 @@ server.add_handler('mt.setPostCategories') do |postid, username, password, categ
494
494
  end
495
495
  src << sec.to_src
496
496
  }
497
-
497
+
498
498
  @cgi.params['old'] = [postid[0,8]]
499
499
  @cgi.params['hide'] = diary.visible? ? [] : ['true']
500
500
  @cgi.params['title'] = [diary.title]
@@ -404,14 +404,14 @@ def theme_convert ( fname, hash )
404
404
  end
405
405
  end
406
406
  }
407
- end
407
+ end
408
408
  end
409
409
 
410
410
  rcss = File::readlines( "append.rcss" ).join
411
411
  File.open( fname.sub( /\.css/i, "-2.css" ), "a" ) do |f|
412
412
  f.write( ERB::new( rcss ).result( binding ) )
413
413
  end
414
- end
414
+ end
415
415
 
416
416
  while cssname = ARGV.shift
417
417
  unless cssname
@@ -422,7 +422,7 @@ while cssname = ARGV.shift
422
422
  begin
423
423
  simplify_css( cssname )
424
424
  rescue
425
- File.delete( cssname.sub( /\.css/i, "-simple.css" ) )
425
+ File.delete( cssname.sub( /\.css/i, "-simple.css" ) )
426
426
  puts "Error!: #{$!}"
427
427
  next
428
428
  end