pastehub 0.2.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +6 -14
- data/README.md +11 -16
- data/Rakefile +32 -79
- data/VERSION.yml +2 -2
- data/bin/PastehubSync +75 -49
- data/{lib/pastehub/store.rb → bin/pastehubGet} +41 -43
- data/bin/pastehubPost +10 -17
- data/lib/pastehub.rb +2 -5
- data/lib/pastehub/client.rb +18 -380
- data/lib/pastehub/clientsync.rb +161 -199
- data/lib/pastehub/clipboard.rb +1 -1
- data/lib/pastehub/config.rb +25 -96
- data/lib/pastehub/syncentry.rb +122 -0
- metadata +64 -71
- data/bin/pastehubDump +0 -114
- data/lib/pastehub/auth.rb +0 -171
- data/lib/pastehub/crypt.rb +0 -70
- data/lib/pastehub/localdb.rb +0 -187
- data/lib/pastehub/log.rb +0 -95
- data/lib/pastehub/macosx.rb +0 -66
- data/lib/pastehub/masterdb.rb +0 -213
- data/server/masterdb.rb +0 -141
- data/server/notifier.rb +0 -89
data/bin/pastehubPost
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# pastehubPost - PasteHub's post utility for UNIX client.
|
5
5
|
#
|
6
|
-
# Copyright (c)
|
6
|
+
# Copyright (c) 2014-2014 Kiyoka Nishiyama <kiyoka@sumibi.org>
|
7
7
|
#
|
8
8
|
# Redistribution and use in source and binary forms, with or without
|
9
9
|
# modification, are permitted provided that the following conditions
|
@@ -33,30 +33,23 @@
|
|
33
33
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
34
|
#
|
35
35
|
#
|
36
|
-
require 'net/http'
|
37
|
-
require 'uri'
|
38
|
-
require 'open-uri'
|
39
|
-
require 'fileutils'
|
40
36
|
require 'pastehub'
|
41
|
-
PasteHub::Config.instance
|
37
|
+
config = PasteHub::Config.instance
|
42
38
|
|
43
39
|
def main
|
44
|
-
username = PasteHub.loadUsername
|
45
|
-
if not username
|
46
|
-
STDERR.puts "clientPost: setup problem. Please setup pastehub application."
|
47
|
-
exit 1
|
48
|
-
end
|
49
|
-
|
50
40
|
# save to LocalDB
|
51
|
-
data
|
52
|
-
|
53
|
-
|
54
|
-
puts client.localSaveValue( nil, data )
|
41
|
+
data = STDIN.read
|
42
|
+
entry = PasteHub::Entry.new( PasteHub.hostname( ) + "__post" )
|
43
|
+
entry.save( data )
|
55
44
|
|
56
45
|
# singal to pastehubSync
|
57
46
|
pid = PasteHub.loadPid
|
58
47
|
if 0 < pid
|
59
|
-
|
48
|
+
begin
|
49
|
+
Process.kill( :SIGUSR1, pid )
|
50
|
+
rescue Errno::ESRCH => e
|
51
|
+
#STDERR.puts( "no such process: pid=#{pid}" )
|
52
|
+
end
|
60
53
|
end
|
61
54
|
end
|
62
55
|
|
data/lib/pastehub.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# pastehub.rb - PasteHub's top-level library file
|
3
3
|
#
|
4
4
|
#
|
5
|
-
# Copyright (c)
|
5
|
+
# Copyright (c) 2014 Kiyoka Nishiyama <kiyoka@sumibi.org>
|
6
6
|
#
|
7
7
|
# Redistribution and use in source and binary forms, with or without
|
8
8
|
# modification, are permitted provided that the following conditions
|
@@ -34,10 +34,7 @@
|
|
34
34
|
#
|
35
35
|
require 'pastehub/config'
|
36
36
|
require 'pastehub/util'
|
37
|
-
require 'pastehub/crypt'
|
38
|
-
require 'pastehub/auth'
|
39
|
-
require 'pastehub/localdb'
|
40
|
-
require 'pastehub/store'
|
41
37
|
require 'pastehub/client'
|
42
38
|
require 'pastehub/clientsync'
|
43
39
|
require 'pastehub/clipboard'
|
40
|
+
require 'pastehub/syncentry'
|
data/lib/pastehub/client.rb
CHANGED
@@ -36,118 +36,38 @@ require 'net/https'
|
|
36
36
|
require 'uri'
|
37
37
|
require 'open-uri'
|
38
38
|
require 'fileutils'
|
39
|
+
require 'socket'
|
39
40
|
|
40
41
|
module PasteHub
|
41
42
|
|
42
|
-
|
43
|
-
signfile = PasteHub::Config.instance.localDbPath + "authinfo.txt"
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.loadUsername
|
47
|
-
signfile = self.signfilePath
|
48
|
-
|
49
|
-
# load authenticate information
|
50
|
-
if not File.exist?( signfile )
|
51
|
-
return nil
|
52
|
-
else
|
53
|
-
begin
|
54
|
-
open( signfile ) {|f|
|
55
|
-
# first line is email (is username)
|
56
|
-
username = f.readline.chomp
|
57
|
-
if username.match( /^[a-z]+/ )
|
58
|
-
return username
|
59
|
-
end
|
60
|
-
}
|
61
|
-
rescue Exception => e
|
62
|
-
STDERR.puts( "Error: can't load #{signfile}: #{e.to_s}" )
|
63
|
-
raise e
|
64
|
-
end
|
65
|
-
return nil
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# setup user's directory
|
43
|
+
# setup user's directory and sync directory
|
70
44
|
# result: true ... success / false ... fail
|
71
45
|
def self.setupDirectory
|
72
|
-
localdb_path
|
46
|
+
localdb_path = PasteHub::Config.instance.localDbPath
|
47
|
+
localsync_path = PasteHub::Config.instance.localSyncPath
|
73
48
|
# Create directory
|
74
49
|
if not File.exist?( localdb_path )
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
50
|
+
FileUtils.mkdir_p( localdb_path, { :mode => 0700 } )
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create directory for Sync
|
54
|
+
if not File.exist?( localsync_path )
|
55
|
+
FileUtils.mkdir_p( localsync_path, { :mode => 0700 } )
|
81
56
|
end
|
82
57
|
return true
|
83
58
|
end
|
84
59
|
|
85
|
-
def self.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
3.times { |n|
|
92
|
-
util.say( "Please input your account information" )
|
93
|
-
username = util.inputText(" email: ")
|
94
|
-
secretKey = util.inputText(" secret-key: " )
|
95
|
-
auth = AuthForClient.new( username, secretKey )
|
96
|
-
client = Client.new( auth )
|
97
|
-
if client.authTest()
|
98
|
-
# save authinfo with gpg
|
99
|
-
begin
|
100
|
-
password = util.inputPasswordTwice(
|
101
|
-
"Please input password for crypted file",
|
102
|
-
" password : ",
|
103
|
-
" password(for verify): " )
|
104
|
-
if password
|
105
|
-
crypt = PasteHub::Crypt.new( password )
|
106
|
-
open( signfile, "w" ) {|f|
|
107
|
-
f.puts( username )
|
108
|
-
f.puts( crypt.en( secretKey ))
|
109
|
-
}
|
110
|
-
# auth OK
|
111
|
-
return [ username, secretKey, password ]
|
112
|
-
end
|
113
|
-
STDERR.puts( "Error: password setting failed..." )
|
114
|
-
rescue Exception => e
|
115
|
-
STDERR.puts( "Error: can't save #{signfile}: #{e.to_s}" )
|
116
|
-
end
|
117
|
-
else
|
118
|
-
STDERR.puts( "your email or secret key is not registerd..." )
|
119
|
-
end
|
120
|
-
}
|
60
|
+
def self.hostname( )
|
61
|
+
hostname = open( "|hostname" ) { |f|
|
62
|
+
f.read.chomp
|
63
|
+
}
|
64
|
+
if 0 < hostname.size()
|
65
|
+
hostname
|
121
66
|
else
|
122
|
-
|
123
|
-
open( signfile ) {|f|
|
124
|
-
util.say( "Please input password for crypted file" )
|
125
|
-
username = f.readline.chomp
|
126
|
-
signStr = f.read
|
127
|
-
3.times { |n|
|
128
|
-
password = util.inputPassword(" crypt password: ")
|
129
|
-
crypt = PasteHub::Crypt.new( password )
|
130
|
-
secretKey= crypt.de( signStr )
|
131
|
-
if secretKey
|
132
|
-
auth = AuthForClient.new( username, secretKey )
|
133
|
-
client = Client.new( auth )
|
134
|
-
if client.authTest()
|
135
|
-
return [ username, secretKey, password ]
|
136
|
-
else
|
137
|
-
STDERR.puts( "Error: your secretKey may be old." )
|
138
|
-
end
|
139
|
-
end
|
140
|
-
STDERR.puts( "Error: missing password." )
|
141
|
-
}
|
142
|
-
}
|
143
|
-
rescue Exception => e
|
144
|
-
STDERR.puts( "Error: can't load #{signfile}: #{e.to_s}" )
|
145
|
-
raise e
|
146
|
-
end
|
67
|
+
raise RuntimeError, "Can't resolve hostname"
|
147
68
|
end
|
148
|
-
return [ nil, nil, nil ]
|
149
69
|
end
|
150
|
-
|
70
|
+
|
151
71
|
def self.savePid( pid )
|
152
72
|
pidFile = PasteHub::Config.instance.localDbPath + "pid"
|
153
73
|
open( pidFile, "w" ) {|f|
|
@@ -168,286 +88,4 @@ module PasteHub
|
|
168
88
|
end
|
169
89
|
return pid
|
170
90
|
end
|
171
|
-
|
172
|
-
|
173
|
-
class ClientBase
|
174
|
-
|
175
|
-
# return: Net::HTTPResponse
|
176
|
-
def httpGet( uriStr, headerHash, errorMessage )
|
177
|
-
uri = URI.parse( uriStr )
|
178
|
-
begin
|
179
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
180
|
-
if ( Net::HTTP.https_default_port == uri.port ) or ( "https" == uri.scheme )
|
181
|
-
https.use_ssl = true
|
182
|
-
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
183
|
-
end
|
184
|
-
https.start {|http|
|
185
|
-
resp = http.get(uri.request_uri, headerHash)
|
186
|
-
if "200" == resp.code
|
187
|
-
return resp
|
188
|
-
end
|
189
|
-
}
|
190
|
-
rescue Exception => e
|
191
|
-
STDERR.puts errorMessage + ":" + e.to_s
|
192
|
-
end
|
193
|
-
return nil
|
194
|
-
end
|
195
|
-
|
196
|
-
# return: Net::HTTPResponse
|
197
|
-
def httpPost( uriStr, bodyStr, headerHash, errorMessage )
|
198
|
-
uri = URI.parse( uriStr )
|
199
|
-
begin
|
200
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
201
|
-
if ( Net::HTTP.https_default_port == uri.port ) or ( "https" == uri.scheme )
|
202
|
-
https.use_ssl = true
|
203
|
-
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
204
|
-
end
|
205
|
-
https.start {|http|
|
206
|
-
resp = http.post(uri.request_uri, bodyStr, headerHash)
|
207
|
-
if "200" == resp.code
|
208
|
-
return resp
|
209
|
-
end
|
210
|
-
}
|
211
|
-
rescue Exception => e
|
212
|
-
STDERR.puts errorMessage + ":" + e.to_s
|
213
|
-
end
|
214
|
-
return nil
|
215
|
-
end
|
216
|
-
|
217
|
-
# return: [ Net::HTTP, Net::HTTP::Get ]
|
218
|
-
def httpGetRequest( uriStr, headerHash, errorMessage )
|
219
|
-
uri = URI.parse( uriStr )
|
220
|
-
begin
|
221
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
222
|
-
if ( Net::HTTP.https_default_port == uri.port ) or ( "https" == uri.scheme )
|
223
|
-
https.use_ssl = true
|
224
|
-
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
225
|
-
end
|
226
|
-
return [ https, Net::HTTP::Get.new(uri.request_uri, headerHash) ]
|
227
|
-
rescue Exception => e
|
228
|
-
STDERR.puts errorMessage + ":" + e.to_s
|
229
|
-
end
|
230
|
-
return nil
|
231
|
-
end
|
232
|
-
|
233
|
-
end
|
234
|
-
|
235
|
-
|
236
|
-
class Client < ClientBase
|
237
|
-
def initialize( auth, password = nil )
|
238
|
-
@auth = auth
|
239
|
-
ins = PasteHub::Config.instance
|
240
|
-
@localdb_path = ins.localDbPath
|
241
|
-
@server_api_url = ins.targetApiURL
|
242
|
-
@server_notifier_url = ins.targetNotifierURL
|
243
|
-
@list_items = ins.listItems
|
244
|
-
@syncTrigger = []
|
245
|
-
@crypt = if password
|
246
|
-
Crypt.new( password )
|
247
|
-
else
|
248
|
-
nil
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
def authTest
|
253
|
-
httpGet( "#{@server_api_url}authTest", @auth.getAuthHash(), "Error: can't connect to server for auth test" )
|
254
|
-
end
|
255
|
-
|
256
|
-
|
257
|
-
def getList( limit = nil )
|
258
|
-
h = {"content-type" => "plain/text"}
|
259
|
-
if limit
|
260
|
-
h[ 'X-Pastehub-Limit' ] = limit.to_i
|
261
|
-
end
|
262
|
-
|
263
|
-
resp = httpGet( "#{@server_api_url}getList", @auth.getAuthHash().merge( h ), "Error: fails 'getList' from server." )
|
264
|
-
str = resp.read_body()
|
265
|
-
masterList = str.split( /\n/ )
|
266
|
-
STDERR.puts "Info: masterList lines = #{masterList.size} #{str.size}Bytes"
|
267
|
-
masterList = masterList.select { |x|
|
268
|
-
okSize = "1340542369=2012-06-24.12:52:49=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".size
|
269
|
-
if okSize != x.size
|
270
|
-
STDERR.puts "Info: masterList(NG): " + x
|
271
|
-
false
|
272
|
-
else
|
273
|
-
x
|
274
|
-
end
|
275
|
-
}
|
276
|
-
masterList
|
277
|
-
end
|
278
|
-
|
279
|
-
def getValue( key )
|
280
|
-
raise RuntimeError, "Error: no encrypt password." unless @crypt
|
281
|
-
|
282
|
-
resp = httpPost( "#{@server_api_url}getValue", key, @auth.getAuthHash().merge( {"content-type" => "plain/text"} ), "Error: fails 'getValue' from server." )
|
283
|
-
ret = @crypt.de( resp.read_body() )
|
284
|
-
unless ret
|
285
|
-
STDERR.puts( "Warning: encrypt password is wrong. getValue missing..." )
|
286
|
-
ret = "error..."
|
287
|
-
end
|
288
|
-
ret
|
289
|
-
end
|
290
|
-
|
291
|
-
def putValue( key, data )
|
292
|
-
ret = ""
|
293
|
-
if not key
|
294
|
-
key = "_"
|
295
|
-
end
|
296
|
-
raise RuntimeError, "Error: no encrypt password." unless @crypt
|
297
|
-
_data = @crypt.en( data )
|
298
|
-
unless _data
|
299
|
-
STDERR.puts( "Warning: encrypt password is wrong. putValue missing..." )
|
300
|
-
ret = nil
|
301
|
-
else
|
302
|
-
resp = httpPost( "#{@server_api_url}putValue", _data,
|
303
|
-
@auth.getAuthHash().merge(
|
304
|
-
{
|
305
|
-
"content-type" => "plain/text",
|
306
|
-
"x-pastehub-key" => key }),
|
307
|
-
"Error: fails 'putValue' from server." )
|
308
|
-
if resp
|
309
|
-
ret = resp.read_body()
|
310
|
-
end
|
311
|
-
end
|
312
|
-
ret
|
313
|
-
end
|
314
|
-
|
315
|
-
def wait_notify( auth )
|
316
|
-
begin
|
317
|
-
pair = httpGetRequest("#{@server_notifier_url}", auth.getAuthHash(), "Error: fails 'notifier' api on server." )
|
318
|
-
https = pair[0]
|
319
|
-
getRequest = pair[1]
|
320
|
-
https.start() { |http|
|
321
|
-
http.request(getRequest) do |response|
|
322
|
-
raise 'Response is not chuncked' unless response.chunked?
|
323
|
-
response.read_body do |chunk|
|
324
|
-
serverValue = chunk.chomp
|
325
|
-
if serverHasNew?( serverValue )
|
326
|
-
puts "Info: server has new data: #{serverValue}"
|
327
|
-
return chunk.chomp.clone()
|
328
|
-
else
|
329
|
-
puts "Info: server is stable: #{serverValue}"
|
330
|
-
end
|
331
|
-
if localHasNew?( )
|
332
|
-
puts "Info: local has new data"
|
333
|
-
return :local
|
334
|
-
end
|
335
|
-
end
|
336
|
-
if "200" != response.code
|
337
|
-
STDERR.puts "Error: request error result=[#{response.code}]"
|
338
|
-
return :retry
|
339
|
-
end
|
340
|
-
end
|
341
|
-
}
|
342
|
-
rescue EOFError => e
|
343
|
-
STDERR.puts "Error: disconnected by server."
|
344
|
-
return :retry
|
345
|
-
rescue Errno::ECONNREFUSED => e
|
346
|
-
STDERR.puts "Error: can't connect to server(ConnectionRefused)."
|
347
|
-
return :retry
|
348
|
-
rescue SocketError => e
|
349
|
-
STDERR.puts "Error: can't connect to server(SocketError)."
|
350
|
-
return :retry
|
351
|
-
rescue Errno::ETIMEDOUT => e
|
352
|
-
STDERR.puts "Error: can't connect to server(Timeout1)."
|
353
|
-
return :retry
|
354
|
-
rescue Timeout::Error => e
|
355
|
-
# ONLINE and notifier has no INFO.
|
356
|
-
return :timeout
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
def serverHasNew?( serverValue )
|
361
|
-
# open local db
|
362
|
-
localdb = PasteHub::LocalDB.new( @localdb_path )
|
363
|
-
localdb.open( @auth.username )
|
364
|
-
localValue = localdb.getValue( PasteHub::SERVER_DATE_KEY )
|
365
|
-
ret = (localValue != serverValue)
|
366
|
-
if ret
|
367
|
-
localdb.insertValue( PasteHub::SERVER_DATE_KEY, serverValue )
|
368
|
-
end
|
369
|
-
localdb.close()
|
370
|
-
return ret
|
371
|
-
end
|
372
|
-
|
373
|
-
def localHasNew?( )
|
374
|
-
localdb = PasteHub::LocalDB.new( @localdb_path )
|
375
|
-
localdb.open( @auth.username )
|
376
|
-
localValue = localdb.getValue( PasteHub::LOCAL_DATE_KEY )
|
377
|
-
serverValue = localdb.getValue( PasteHub::SERVER_DATE_KEY )
|
378
|
-
ret = if localValue and serverValue
|
379
|
-
(localValue > serverValue)
|
380
|
-
else
|
381
|
-
false
|
382
|
-
end
|
383
|
-
if ret
|
384
|
-
localdb.insertValue( PasteHub::LOCAL_DATE_KEY, serverValue )
|
385
|
-
end
|
386
|
-
localdb.close()
|
387
|
-
return ret
|
388
|
-
end
|
389
|
-
|
390
|
-
def setOnlineState( online )
|
391
|
-
# open local db
|
392
|
-
if online
|
393
|
-
if online?() == false
|
394
|
-
@syncTrigger.unshift( true )
|
395
|
-
end
|
396
|
-
end
|
397
|
-
localdb = PasteHub::LocalDB.new( @localdb_path )
|
398
|
-
localdb.open( @auth.username )
|
399
|
-
localdb.insertValue( PasteHub::ONLINE_STATE_KEY, online ? "1" : "0" )
|
400
|
-
localdb.close()
|
401
|
-
end
|
402
|
-
|
403
|
-
def online?( )
|
404
|
-
# open local db
|
405
|
-
localdb = PasteHub::LocalDB.new( @localdb_path )
|
406
|
-
localdb.open( @auth.username, true )
|
407
|
-
# printf( "[%s]", localdb.getValue( PasteHub::ONLINE_STATE_KEY ))
|
408
|
-
ret = ("1" == localdb.getValue( PasteHub::ONLINE_STATE_KEY ))
|
409
|
-
localdb.close()
|
410
|
-
ret
|
411
|
-
end
|
412
|
-
|
413
|
-
def getTrigger()
|
414
|
-
if 0 < @syncTrigger.size
|
415
|
-
return @syncTrigger.pop
|
416
|
-
end
|
417
|
-
return false
|
418
|
-
end
|
419
|
-
|
420
|
-
def localSaveValue( argKey = nil, data )
|
421
|
-
# open local db
|
422
|
-
util = PasteHub::Util.new( )
|
423
|
-
if argKey
|
424
|
-
key = argKey
|
425
|
-
else
|
426
|
-
key = util.currentTime( ) + "=" + util.digest( data )
|
427
|
-
end
|
428
|
-
|
429
|
-
localdb = PasteHub::LocalDB.new( @localdb_path )
|
430
|
-
localdb.open( @auth.username )
|
431
|
-
list = localdb.getList( )
|
432
|
-
if util.key_digest( list[0] ) == util.digest( data )
|
433
|
-
# duplicate
|
434
|
-
localdb.close()
|
435
|
-
list[0]
|
436
|
-
else
|
437
|
-
localdb.insertValue( key, data.dup )
|
438
|
-
localdb.insertValue( PasteHub::LOCAL_DATE_KEY, util.currentTime( ) )
|
439
|
-
localdb.close()
|
440
|
-
key
|
441
|
-
end
|
442
|
-
end
|
443
|
-
|
444
|
-
def setServerFlags( keys )
|
445
|
-
localdb = PasteHub::LocalDB.new( @localdb_path )
|
446
|
-
localdb.open( @auth.username )
|
447
|
-
keys.each { |key|
|
448
|
-
localdb.setServerFlag( key )
|
449
|
-
}
|
450
|
-
localdb.close()
|
451
|
-
end
|
452
|
-
end
|
453
91
|
end
|