This file is indexed.

/usr/share/tdiary/contrib/plugin/tdiarytimes2.rb is in tdiary-contrib 5.0.8-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# tdiarytimes.rb $originalRevision: 1.1 $
#
# Copyright (c) 2003 neuichi <neuichi@nmnl.jp>
# Distributed under the GPL
#
# 2003-12-01 circle extention added by Minero Aoki <aamine@loveruby.net>
# $Id: tdiarytimes2.rb,v 1.2 2007/01/11 02:55:26 tadatadashi Exp $
#
# プラグイン配布ページ
# http://i.loveruby.net/w/tdiarytimes.html
#
# 動作条件:
# ruby-gdが使える環境が必要です。
#
# 使い方:
# このプラグインをプラグインディレクトリに入れ、
# index.rbと同じディレクトリに、tdiarytimes.pngという名前の
# サーバが書き込み権限を持っているファイルを作ります。
#	これで日記に書き込みするごとに、tdiarytimes.pngに
#	画像を書き込みます。
#
# 日記上からこのpngファイルを呼び出すには、
# tDiray上からプラグインとして
# <%=tdiarytimes%>
# として呼び出します。
# 引数としてimgタグのaltの文字列を指定することも出来ます。
# <%=tdiarytimes '文字列'%>
#
# また、tdiary.confに以下のオプションを書き込むことにより、
# カスタマイズをすることが出来ます。
#
# @options['tdiarytimes.width'] = 400
# 四角の横幅。デフォルト値400。
# 実際に出力される画像サイズは、これに+10したサイズ。
#
# @options['tdiarytimes.height'] = 20
# 四角の縦幅。デフォルト値20。
# 実際に出力される画像サイズは、これに+16したサイズ。
#
# @options['tdiarytimes.file'] = 'tdiarytimes.png'
# 出力する画像ファイル名。デフォルトは'tdiarytimes.png'
#
# @options['tdiarytimes.fillcolor'] = '#444444'
# 四角の色。デフォルトは'#444444'
#
# @options['tdiarytimes.linecolor'] = '#ffffff'
# 縦棒の色。デフォルトは'#ffffff'
#
# @options['tdiarytimes.textcolor'] = '#444444'
# 文字色。デフォルトは'#444444'
#
# @options['tdiarytimes.fadeout'] = false
# フェードアウトするか。デフォルトはfalse。
# フェードアウトしたいときには true にすればよい。
#
# @options['tdiarytimes.fadeoutcolor'] = '#ffffff'
# フェードアウトするとき、
# デフォルトではfillcolorへとフェードアウトしていく。
# ここで色を指定するとその色へとフェードアウトしていく。
# デフォルトは false
#
# @options['tdiarytimes.text'] = 'T D I A R Y T I M E S'
# 出力する文字。デフォルトは'T D I A R Y T I M E S'。なお半角英数字のみ対応。
#
# @options['tdiarytimes.day'] = 30
# ログを保存する最大日数。デフォルトは30。
# この場合、30日以上経ったデータは消去され、縦棒として描画されなくなる。
#

require 'GD'

::GD::Image.module_eval {
  def tiny_string(text, x, y, color)
    string(GD::Font::TinyFont, x, y, text, color)
  end

  def small_string(text, x, y, color)
    string(GD::Font::SmallFont, x, y, text, color)
  end
}

# Ruby 1.6 missing File.read
unless ::File.respond_to?(:read)
  def (::File).read(fname)
    File.open(fname) {|f|
      return f.read
    }
  end
end

# Ruby 1.6 missing MatchData#captures
unless ::MatchData.method_defined?(:captures)
  ::MatchData.module_eval {
    def captures
      a = to_a()
      a.shift
      a
    end
  }
end

class TDiaryTimes
  class << TDiaryTimes
    alias newobj new
  end

  def TDiaryTimes.new(datadir, options)
    case options['tdiarytimes.shape']
    when 'bar', nil
      c = TDiaryTimesBar
    when 'circle'
      c = TDiaryTimesCircle
    else
      raise ArgumentError, "unknown tdiarytimes.shape: #{options['tdiarytimes.shape']}"
    end
    c.newobj("#{datadir}/tdiarytimes", options)
  end

  def initialize(dbfile, options)
    @dbfile     = dbfile
    @image_file = options['tdiarytimes.file'] || 'tdiarytimes.png'
    @day        = options['tdiarytimes.day'] || 30
    @keepdb     = options['tdiarytimes.keepdb']
  end

  attr_reader :image_file

  def update_image
    now = Time.now
    mtimes = (load_database() + [now]).reject {|tm|
               (now - tm) > (60 * 60 * 24 * @day)
             }
    image = create_image(mtimes)
    File.open(@image_file, 'w') {|png|
      image.png(png)
    }
    save_database(mtimes) unless @keepdb
  end

  private

  #
  # database
  #

  def load_database
    begin
      return Marshal.load(File.read(@dbfile))
    rescue Errno::ENOENT
      return []
    end
  end

  def save_database(content)
    File.open(@dbfile, 'w') {|f|
      Marshal.dump(content, f)
    }
  end

  #
  # common paint methods
  #

  def fadeout_color(srccolor, destcolor, time)
    par = (Time.now - time).to_f / (60 * 60 * 24 * @day)
    r, g, b = *zip(parse_rgb(srccolor), parse_rgb(destcolor))\
        .map {|src, dest| src - (src - dest) * par }.map {|c| c.to_i }
    sprintf('#%02x%02x%02x', r, g, b)
  end

  def parse_rgb(str)
    hex = '[\da-f]'
    m = /\A\#(#{hex}{2})(#{hex}{2})(#{hex}{2})\z/io.match(str) or
        raise ArgumentError, "tdiarytimes: not color: #{str.inspect}"
    m.captures.map {|c| c.hex }
  end

  def zip(*lists)
    result = []
    lists[0].each_index do |idx|
      result.push lists.map {|lst| lst[idx] }
    end
    result
  end
end

class TDiaryTimesBar < TDiaryTimes
  def initialize(dbfile, options)
    super
    @text         = options['tdiarytimes.text'] || 'T D I A R Y T I M E S'
    @width        = options['tdiarytimes.width'].to_i || 400
    @height       = options['tdiarytimes.height'].to_i || 20
    @textcolor    = options['tdiarytimes.textcolor'] || '#444444'
    @fillcolor    = options['tdiarytimes.fillcolor'] || '#444444'
    @linecolor    = options['tdiarytimes.linecolor'] || '#ffffff'
    @fadeoutcolor = options['tdiarytimes.fadeoutcolor'] || @fillcolor
    @fadeoutp     = options['tdiarytimes.fadeout']
  end

  def html(alt)
    %Q[<img src="#{h image_file()}"
            alt="#{h( alt || @text )}"
            width="#{@width + GAP_W}"
            height="#{@height + GAP_H}"
            class="tdiarytimes">].gsub(/\s+/, ' ')
  end

  private

  GAP_W = 16
  GAP_H = 16

  def create_image(mtimes)
    image = GD::Image.new(@width + GAP_W, @height + GAP_H)
    image.transparent(image.colorAllocate('#fffffe'))
    image.interlace = true

    image.tiny_string @text, (GAP_W / 2), 0, image.colorAllocate(@textcolor)
    image.filledRectangle           0 + GAP_W / 2,            0 + GAP_H / 2,
                          image.width - GAP_W / 2, image.height - GAP_H / 2,
                          image.colorAllocate(@fillcolor)
    if @fadeoutp
      paint_lines_fadeout image, mtimes, @linecolor, @fadeoutcolor
    else
      paint_lines         image, mtimes, @linecolor
    end
    paint_hours image, image.colorAllocate(@textcolor),
                (image.width - GAP_W > 160 ? 2 : 4)

    image
  end

  def paint_lines(image, mtimes, color)
    gdcolor = image.colorAllocate(color)
    mtimes.each do |time|
      line image, time, gdcolor
    end
  end

  def paint_lines_fadeout(image, mtimes, linecolor, destcolor)
    mtimes.each do |time|
      line image, time,
           image.colorAllocate(fadeout_color(linecolor, destcolor, time))
    end
  end

  def line(image, time, color)
    x0 = (image.width - GAP_W).to_f * (time.hour * 60 + time.min) / (60 * 24)
    x = (x0 + (GAP_W / 1.25)).to_i
    image.line x,            0 + (GAP_H / 2),
               x, image.height - (GAP_H / 2),
               color
  end

  def paint_hours(image, color, stepping)
    0.step(24, stepping) do |hour|
      image.tiny_string hour.to_s,
          (image.width - GAP_W) * (hour.to_f / 24) + (GAP_W / 2) - 4,
          image.height - (GAP_H / 2),
          color
    end
  end
end

class TDiaryTimesCircle < TDiaryTimes
  def initialize(dbfile, options)
    super
    #@text   # cannot change now
    @width        = options['tdiarytimes.width'].to_i || 80
    @height       = options['tdiarytimes.height'].to_i || 80
    @textcolor    = options['tdiarytimes.textcolor'] || '#444444'
    @fillcolor    = options['tdiarytimes.fillcolor'] || '#444444'
    @linecolor    = options['tdiarytimes.linecolor'] || '#ffffff'
    @fadeoutcolor = options['tdiarytimes.fadeoutcolor'] || @fillcolor
    @fadeoutp     = options['tdiarytimes.fadeout']
  end

  def html(alt)
    %Q[<img src="#{h image_file()}"
            alt="#{h( alt || '' )}"
            width="#{@width}"
            height="#{@height}"
            class="tdiarytimes">].gsub(/\s+/, ' ')
  end

  private

  MIN_DEGREE = 0
  MAX_DEGREE = 250
  BAR_WIDTH = 24
  TRANSCOLOR = '#ffffff'

  def create_image(mtimes)
    image = GD::Image.new(@width, @height)
    trans = image.colorAllocate(TRANSCOLOR)
    image.transparent trans
    image.interlace = true

    paint_outer_circle image, trans
    if @fadeoutp
      paint_lines_fadeout image, mtimes, @linecolor, @fadeoutcolor
    else
      paint_lines         image, mtimes, @linecolor
    end
    paint_inner_circle image, trans
    textcolor = image.colorAllocate(@textcolor)
    image.small_string 'tdiary', @width / 2 + 1, 11, textcolor
    image.small_string 'times',  @width / 2 + 4, 21, textcolor

    image
  end

  def paint_outer_circle(image, trans)
    image.filledArc @width / 2, @height / 2,
                    @width, @height,
                    MIN_DEGREE, MAX_DEGREE,
                    if @fillcolor == TRANSCOLOR
                        then trans
                        else image.colorAllocate(@fillcolor)
                        end,
                    0
  end

  def paint_inner_circle(image, trans)
    image.filledArc @width / 2, @height / 2,
                    @width - BAR_WIDTH * 2,
                    (@width - BAR_WIDTH * 2) * (@height.to_f / @width),
                    0, 360, trans, 0
  end

  def paint_lines(image, mtimes, color)
    gdcolor = image.colorAllocate(color)
    mtimes.each do |time|
      line image, time, gdcolor
    end
  end

  def paint_lines_fadeout(image, mtimes, linecolor, destcolor)
    mtimes.each do |time|
      line image, time,
           image.colorAllocate(fadeout_color(linecolor, destcolor, time))
    end
  end

  def line(image, time, color)
    d0 = (time.hour * 60 + time.min).to_f / (60 * 24)
    d = MIN_DEGREE + (MAX_DEGREE - MIN_DEGREE) * d0
    image.line @width / 2, @height / 2,
               @width  / 2 + degcos(d) * (@width  / 2) * 0.95,
               @height / 2 + degsin(d) * (@height / 2) * 0.95,
               color
  end

  include Math

  def degsin(d)
    sin(d / (180 / Math::PI))
  end

  def degcos(d)
    cos(d / (180 / Math::PI))
  end
end

def tdiarytimes(alt = nil)
  TDiaryTimes.new(@conf.data_path, @options).html(alt)
end


if $0 == __FILE__   # debugging
  tmp_options_bar = {
    'tdiarytimes.shape'     => 'bar',
    'tdiarytimes.textcolor' => '#666666',
    'tdiarytimes.linecolor' => '#df0000',
    'tdiarytimes.fillcolor' => '#0f5f0f',
    'tdiarytimes.fadeout'   => true,
    'tdiarytimes.keepdb'    => false   # for debug
  }
  tmp_options_circle = {
    'tdiarytimes.shape'     => 'circle',
    'tdiarytimes.textcolor' => '#000000',
    'tdiarytimes.linecolor' => '#bfbfbf',
    'tdiarytimes.fillcolor' => '#2f2f7f',
    'tdiarytimes.fadeout'   => true,
    'tdiarytimes.keepdb'    => false   # for debug
  }

  @mode = 'latest'
  @conf = Object.new
  def @conf.data_path
    '.'
  end
  case ARGV[0]
  when 'bar'
    @options = tmp_options_bar
  else
    @options = tmp_options_circle
  end
  TDiaryTimes.new(@conf.data_path, @options).update_image
  puts tdiarytimes()
  exit 0
end

if /append|replace/ =~ @mode
  TDiaryTimes.new(@conf.data_path, @options).update_image
end