livejournal 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +17 -0
- data/README +50 -0
- data/Rakefile +60 -0
- data/lib/livejournal/basic.rb +59 -0
- data/lib/livejournal/comment.rb +82 -0
- data/lib/livejournal/comments-xml.rb +158 -0
- data/lib/livejournal/database.rb +292 -0
- data/lib/livejournal/entry.rb +280 -0
- data/lib/livejournal/friends.rb +102 -0
- data/lib/livejournal/login.rb +43 -0
- data/lib/livejournal/logjam.rb +76 -0
- data/lib/livejournal/request.rb +126 -0
- data/lib/livejournal/sync.rb +185 -0
- data/sample/export +154 -0
- data/sample/lj +23 -0
- data/setup.rb +1585 -0
- data/test/checkfriends.rb +29 -0
- data/test/comments-xml.rb +108 -0
- data/test/database.rb +54 -0
- data/test/time.rb +49 -0
- metadata +60 -0
@@ -0,0 +1,280 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'livejournal/request'
|
26
|
+
|
27
|
+
module LiveJournal
|
28
|
+
# LiveJournal times have no time zone, as they are for display only:
|
29
|
+
# "I wrote this post at midnight". However, it's convenient to represent
|
30
|
+
# times with a Ruby time object. But when time zones get involved,
|
31
|
+
# everything gets confused; we'd like to store a Unix time in the database
|
32
|
+
# and those only make sense as GMT. To reduce confusion, then, we imagine
|
33
|
+
# all LiveJournal times are in GMT.
|
34
|
+
# This function takes a time in any time zone and just switches the
|
35
|
+
# timezone to GMT. That is, coerce_gmt of 11:12pm PST is 11:12 pm GMT.
|
36
|
+
# The entry time-setting functions require this GMT part to verify you're
|
37
|
+
# thinking carefully about time when you use Entry#time. If I want an
|
38
|
+
# entry that has a time that corresponds to what I feel is "now", I'd use
|
39
|
+
# LiveJournal::coerce_gmt Time.now
|
40
|
+
def self.coerce_gmt time
|
41
|
+
expanded = time.to_a
|
42
|
+
expanded[8] = false # dst flag
|
43
|
+
expanded[9] = 'GMT'
|
44
|
+
return Time.gm(*expanded)
|
45
|
+
end
|
46
|
+
|
47
|
+
class Entry
|
48
|
+
attr_accessor :itemid, :anum, :subject, :event, :moodid, :mood
|
49
|
+
attr_accessor :music, :taglist, :pickeyword, :preformatted, :backdated
|
50
|
+
attr_accessor :comments # values: {:normal, :none, :noemail}
|
51
|
+
attr_reader :time # a Ruby Time object
|
52
|
+
attr_accessor :security # values: {:public, :private, :friends, :custom}
|
53
|
+
attr_accessor :allowmask
|
54
|
+
attr_accessor :screening # values {:default, :all, :anonymous, :nonfriends, :none}
|
55
|
+
attr_accessor :props
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@subject = nil
|
59
|
+
@event = nil
|
60
|
+
@moodid = nil
|
61
|
+
@mood = nil
|
62
|
+
@music = nil
|
63
|
+
@taglist = []
|
64
|
+
@pickeyword = nil
|
65
|
+
@preformatted = false
|
66
|
+
@backdated = false
|
67
|
+
@comments = :normal
|
68
|
+
@time = nil
|
69
|
+
@security = :public
|
70
|
+
@allowmask = nil
|
71
|
+
@screening = :default
|
72
|
+
@props = {}
|
73
|
+
end
|
74
|
+
|
75
|
+
def ==(other)
|
76
|
+
[:subject, :event, :moodid, :mood, :music, :taglist, :pickeyword,
|
77
|
+
:preformatted, :backdated, :comments, :time, :security, :allowmask,
|
78
|
+
:screening, :props].each do |attr|
|
79
|
+
return false if send(attr) != other.send(attr)
|
80
|
+
end
|
81
|
+
return true
|
82
|
+
end
|
83
|
+
|
84
|
+
def time=(time)
|
85
|
+
raise RuntimeError, "Must use GMT times everywhere to reduce confusion. See LiveJournal::coerce_gmt for details." unless time.gmt?
|
86
|
+
@time = time
|
87
|
+
end
|
88
|
+
|
89
|
+
def from_request(req)
|
90
|
+
@itemid, @anum = req['itemid'].to_i, req['anum'].to_i
|
91
|
+
@subject, @event = req['subject'], CGI.unescape(req['event'])
|
92
|
+
|
93
|
+
case req['security']
|
94
|
+
when 'public'
|
95
|
+
@security = :public
|
96
|
+
when 'private'
|
97
|
+
@security = :private
|
98
|
+
when 'usemask'
|
99
|
+
if req['allowmask'] == '1'
|
100
|
+
@security = :friends
|
101
|
+
else
|
102
|
+
@security = :custom
|
103
|
+
@allowmask = req['allowmask'].to_i
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
@time = LiveJournal::Request::ljtime_to_time req['eventtime']
|
108
|
+
|
109
|
+
# further metadata is loaded via #load_prop
|
110
|
+
|
111
|
+
self
|
112
|
+
end
|
113
|
+
def load_prop(name, value) #:nodoc:#
|
114
|
+
case name
|
115
|
+
when 'current_mood'
|
116
|
+
@mood = value.to_i
|
117
|
+
when 'current_moodid'
|
118
|
+
@moodid = value.to_i
|
119
|
+
when 'current_music'
|
120
|
+
@music = value
|
121
|
+
when 'taglist'
|
122
|
+
@taglist = value.split(/, /).sort
|
123
|
+
when 'picture_keyword'
|
124
|
+
@pickeyword = value
|
125
|
+
when 'opt_preformatted'
|
126
|
+
@preformatted = value == '1'
|
127
|
+
when 'opt_nocomments'
|
128
|
+
@comments = :none
|
129
|
+
when 'opt_noemail'
|
130
|
+
@comments = :noemail
|
131
|
+
when 'opt_backdated'
|
132
|
+
@backdated = value == '1'
|
133
|
+
when 'opt_screening'
|
134
|
+
case value
|
135
|
+
when 'A'; @screening = :all
|
136
|
+
when 'R'; @screening = :anonymous
|
137
|
+
when 'F'; @screening = :nonfriends
|
138
|
+
when 'N'; @screening = :none
|
139
|
+
else
|
140
|
+
raise LiveJournalException,
|
141
|
+
"unknown opt_screening value #{value.inspect}"
|
142
|
+
end
|
143
|
+
when 'hasscreened'
|
144
|
+
@screened = value == '1'
|
145
|
+
# and then some props we just store by name
|
146
|
+
when 'revnum'; @props[name] = value
|
147
|
+
when 'revtime'; @props[name] = value
|
148
|
+
when 'commentalter'; @props[name] = value
|
149
|
+
when 'unknown8bit'; @props[name] = value
|
150
|
+
else
|
151
|
+
@props[name] = value
|
152
|
+
raise Request::ProtocolException, "unknown prop (#{name}, #{value})"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Get the numeric id used in URLs (it's a function of the itemid and the
|
157
|
+
# anum).
|
158
|
+
def display_itemid
|
159
|
+
(@itemid << 8) + @anum
|
160
|
+
end
|
161
|
+
|
162
|
+
# Render LJ markup to an HTML simulation.
|
163
|
+
# (The server to use is for rendering links to other LJ users.)
|
164
|
+
def event_as_html server=LiveJournal::DEFAULT_SERVER
|
165
|
+
# I'd like to use REXML but the content isn't XML, so REs it is!
|
166
|
+
html = @event.dup
|
167
|
+
html.gsub!(/\n/, "<br/>\n") unless @preformatted
|
168
|
+
html.gsub!(%r{< \s* lj \s+ user \s* = \s*
|
169
|
+
['"]? ([^\s'"]+) ['"]?
|
170
|
+
\s* /? \s* >}ix) do
|
171
|
+
user = $1
|
172
|
+
url = "#{server.url}/~#{user}/"
|
173
|
+
"<a href='#{url}'><b>#{user}</b></a>"
|
174
|
+
end
|
175
|
+
html
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
module Request
|
180
|
+
class GetEvents < Req
|
181
|
+
# We support three different types of GetEvents:
|
182
|
+
# * <tt>GetEvents.new(user, :itemid => itemid)</tt> (fetch a single item)
|
183
|
+
# * <tt>GetEvents.new(user, :recent => n)</tt> (fetch most recent n itemds)
|
184
|
+
# * <tt>GetEvents.new(user, :lastsync => lastsync)</tt> (for syncing)
|
185
|
+
def initialize(user, opts)
|
186
|
+
super(user, 'getevents')
|
187
|
+
self['lineendings'] = 'unix'
|
188
|
+
|
189
|
+
if opts.has_key? :itemid
|
190
|
+
self['selecttype'] = 'one'
|
191
|
+
self['itemid'] = opts[:itemid]
|
192
|
+
elsif opts.has_key? :recent
|
193
|
+
self['selecttype'] = 'lastn'
|
194
|
+
self['howmany'] = opts[:recent]
|
195
|
+
elsif opts.has_key? :lastsync
|
196
|
+
self['selecttype'] = 'syncitems'
|
197
|
+
self['lastsync'] = opts[:lastsync] if opts[:lastsync]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns either a single #Entry or an array of #Entry, depending on
|
202
|
+
# the mode this was constructed with.
|
203
|
+
def run
|
204
|
+
super
|
205
|
+
|
206
|
+
entries = {}
|
207
|
+
each_in_array('events') do |req|
|
208
|
+
entry = Entry.new.from_request(req)
|
209
|
+
entries[entry.itemid] = entry
|
210
|
+
end
|
211
|
+
|
212
|
+
each_in_array('prop') do |prop|
|
213
|
+
itemid = prop['itemid'].to_i
|
214
|
+
entries[itemid].load_prop(prop['name'], prop['value'])
|
215
|
+
end
|
216
|
+
|
217
|
+
if @reqparams.has_key? 'itemid'
|
218
|
+
return entries[@reqparams['itemid']]
|
219
|
+
else
|
220
|
+
return entries
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
class EditEvent < Req
|
225
|
+
def initialize(user, entry, opts={})
|
226
|
+
super(user, 'editevent')
|
227
|
+
self['itemid'] = entry.itemid
|
228
|
+
if entry.event
|
229
|
+
self['event'] = entry.event
|
230
|
+
elsif entry.entry.nil? and opts.has_key? :delete
|
231
|
+
self['event'] = ''
|
232
|
+
else
|
233
|
+
raise AccidentalDeleteError
|
234
|
+
end
|
235
|
+
self['lineendings'] = 'unix'
|
236
|
+
self['subject'] = entry.subject
|
237
|
+
|
238
|
+
case entry.security
|
239
|
+
when :public
|
240
|
+
self['security'] = 'public'
|
241
|
+
when :friends
|
242
|
+
self['security'] = 'usemask'
|
243
|
+
self['allowmask'] = 1
|
244
|
+
when :private
|
245
|
+
self['security'] = 'private'
|
246
|
+
when :custom
|
247
|
+
self['security'] = 'usemask'
|
248
|
+
self['allowmask'] = entry.allowmask
|
249
|
+
end
|
250
|
+
|
251
|
+
self['year'], self['mon'], self['day'] =
|
252
|
+
entry.time.year, entry.time.mon, entry.time.day
|
253
|
+
self['hour'], self['min'] = entry.time.hour, entry.time.min
|
254
|
+
|
255
|
+
{ 'current_mood' => entry.mood,
|
256
|
+
'current_moodid' => entry.moodid,
|
257
|
+
'current_music' => entry.music,
|
258
|
+
'picture_keyword' => entry.pickeyword,
|
259
|
+
'taglist' => entry.taglist.join(', '),
|
260
|
+
'opt_preformatted' => entry.preformatted ? 1 : 0,
|
261
|
+
'opt_nocomments' => entry.comments == :none ? 1 : 0,
|
262
|
+
'opt_noemail' => entry.comments == :noemail ? 1 : 0,
|
263
|
+
'opt_backdated' => entry.backdated ? 1 : 0,
|
264
|
+
'opt_screening' =>
|
265
|
+
case entry.screening
|
266
|
+
when :all; 'A'
|
267
|
+
when :anonymous; 'R'
|
268
|
+
when :nonfriends; 'F'
|
269
|
+
when :none; 'N'
|
270
|
+
when :default; ''
|
271
|
+
end
|
272
|
+
}.each do |name, value|
|
273
|
+
self["prop_#{name}"] = value
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# vim: ts=2 sw=2 et :
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'livejournal/request'
|
26
|
+
|
27
|
+
module LiveJournal
|
28
|
+
# Represents a LiveJournal friend relationship.
|
29
|
+
# See LiveJournal::Request::Friends to get an array of these.
|
30
|
+
class Friend
|
31
|
+
attr_accessor :username, :fullname
|
32
|
+
attr_accessor :background, :foreground, :groupmask, :type
|
33
|
+
def initialize
|
34
|
+
@username = nil
|
35
|
+
@fullname = nil
|
36
|
+
@background = nil
|
37
|
+
@foreground = nil
|
38
|
+
@groupmask = nil
|
39
|
+
@type = nil
|
40
|
+
end
|
41
|
+
def from_request(req)
|
42
|
+
@username = req['user']
|
43
|
+
@fullname = req['name']
|
44
|
+
@foreground = req['fg']
|
45
|
+
@background = req['bg']
|
46
|
+
@groupmask = req['groupmask']
|
47
|
+
@type = req['type']
|
48
|
+
self
|
49
|
+
end
|
50
|
+
def to_s
|
51
|
+
"#{@username}: #{@fullname}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Request
|
56
|
+
class Friends < Req
|
57
|
+
attr_reader :friends
|
58
|
+
def initialize(user)
|
59
|
+
super(user, 'getfriends')
|
60
|
+
@friends = nil
|
61
|
+
end
|
62
|
+
# Returns an array of LiveJournal::Friend.
|
63
|
+
def run
|
64
|
+
super
|
65
|
+
@friends = build_array('friend') { |r| Friend.new.from_request(r) }
|
66
|
+
@friends
|
67
|
+
end
|
68
|
+
end
|
69
|
+
class FriendOfs < Req
|
70
|
+
attr_reader :friendofs
|
71
|
+
def initialize(user)
|
72
|
+
super(user, 'friendof')
|
73
|
+
@friendofs = nil
|
74
|
+
end
|
75
|
+
# Returns an array of LiveJournal::Friend.
|
76
|
+
def run
|
77
|
+
super
|
78
|
+
@friends = build_array('friendof') { |r| Friend.new.from_request(r) }
|
79
|
+
@friends
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class CheckFriends < Req
|
84
|
+
attr_reader :interval
|
85
|
+
def initialize(user, lastupdate=nil)
|
86
|
+
super(user, 'checkfriends')
|
87
|
+
@lastupdate = lastupdate
|
88
|
+
@interval = 90 # reasonable default?
|
89
|
+
end
|
90
|
+
# Returns true if there are new posts available.
|
91
|
+
def run
|
92
|
+
self['lastupdate'] = @lastupdate if @lastupdate
|
93
|
+
super
|
94
|
+
@lastupdate = self['lastupdate']
|
95
|
+
@interval = self['interval']
|
96
|
+
self['new'] == '1'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# vim: ts=2 sw=2 et :
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'livejournal/request'
|
26
|
+
|
27
|
+
module LiveJournal
|
28
|
+
module Request
|
29
|
+
class Login < Req
|
30
|
+
def initialize(user)
|
31
|
+
super(user, 'login')
|
32
|
+
end
|
33
|
+
def run
|
34
|
+
super
|
35
|
+
u = @user # should we clone here?
|
36
|
+
u.fullname = @result['name']
|
37
|
+
u
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# vim: ts=2 sw=2 et :
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
#
|
25
|
+
# This module extends the LiveJournal module to work with LogJam's data.
|
26
|
+
|
27
|
+
require 'rexml/document' # parsing logjam conf
|
28
|
+
|
29
|
+
module LiveJournal
|
30
|
+
module LogJam
|
31
|
+
# Path to LogJam data.
|
32
|
+
def self.logjam_path
|
33
|
+
File.expand_path '~/.logjam'
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.xml_fetch(file, path) #:nodoc:
|
37
|
+
doc = REXML::Document.new(File.open(file))
|
38
|
+
doc.elements.each(path) { |element| return element.text }
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Name of LogJam's current server.
|
43
|
+
def self.current_server
|
44
|
+
xml_fetch(logjam_path + '/conf.xml', '/configuration/currentserver')
|
45
|
+
end
|
46
|
+
|
47
|
+
# Path to LogJam's data for a given server.
|
48
|
+
def self.server_path servername
|
49
|
+
logjam_path + '/servers/' + servername # is escaping needed here?
|
50
|
+
end
|
51
|
+
|
52
|
+
# Username for a given server's current user.
|
53
|
+
def self.current_user servername
|
54
|
+
xml_fetch(server_path(servername) + '/conf.xml',
|
55
|
+
'/server/currentuser')
|
56
|
+
end
|
57
|
+
|
58
|
+
# Path to a given user's data.
|
59
|
+
def self.user_path servername, username
|
60
|
+
server_path(servername) + "/users/#{username}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return [current_server, current_user].
|
64
|
+
def self.current_server_user
|
65
|
+
server = current_server
|
66
|
+
user = current_user server
|
67
|
+
[server, user]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.database_from_server_user servername, username
|
71
|
+
Database.new(LogJam::user_path(servername, username) + "/journal.db")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# vim: ts=2 sw=2 et :
|