View difference between Paste ID: 7f7Mdhrx and 4ZRHE4Ar
SHOW: | | - or go back to the newest paste.
1
--[[
2
	Whisk - File/Folder Transmitter for ComputerCraft
3
	 by EldidiStroyrr
4
5
	Use the GUI by running w/o arguments
6
	
7
	get with
8-
	 pastebin get 4ZRHE4Ar whisk
8+
	 pastebin get 7f7Mdhrx whisk
9-
     std pb 4ZRHE4Ar whisk
9+
     std pb 7f7Mdhrx whisk
10
     std ld whisk whisk
11
	working on:
12
	 -gui for file selection
13
14
	Whisk is now on SimSoft! Install w/ storecode jVELp2st
15
--]]
16
17
local channel = 2846
18
local modem = peripheral.find("modem")
19
20
local yield = function()
21
	os.queueEvent("yield")
22
	os.pullEvent("yield")
23
end
24
25
local displayHelp = function()
26
	local helptxt = [[
27
Whisk - file/folder sender
28
29
Syntax:
30
 whisk
31
 whisk send <path> [idfilter] [password]
32
 whisk receive [path] [idfilter] [password]
33
]]
34
	write(helptxt)
35
end
36
37
fixstr = function(str) --replaces those annoying tabs with spaces, which fixes encryption
38
	if not type(str) == "string" then return str end
39
	local fix = string.gsub(str,string.char(9),"  ")
40
	return fix
41
end
42
43
44
45
46
local lddfm = {} --main API
47
lddfm.scr_x, lddfm.scr_y = term.getSize()
48
lddfm.scroll = 0
49
lddfm.ypaths = {}
50
51
lddfm.setPalate = function(_p)
52
	if type(_p) ~= "table" then
53
		_p = {}
54
	end
55
	lddfm.p = { --the DEFAULT color palate
56
		bg =        _p.bg or colors.gray,			-- whole background color
57
		d_txt =     _p.d_txt or colors.yellow,		-- directory text color
58
		d_bg =      _p.d_bg or colors.gray,			-- directory bg color
59
		f_txt =     _p.f_txt or colors.white,		-- file text color
60
		f_bg =      _p.f_bg or colors.gray,			-- file bg color
61
		p_txt =     _p.p_txt or colors.black,		-- path text color
62
		p_bg =      _p.p_bg or colors.lightGray,	-- path bg color
63
		close_txt = _p.close_txt or colors.gray,	-- close button text color
64
		close_bg =  _p.close_bg or colors.lightGray,-- close button bg color
65
		scr =       _p.scr or colors.lightGray,		-- scrollbar color
66
		scrbar =    _p.scrbar or colors.gray,		-- scroll tab color
67
	}
68
end
69
70
lddfm.setPalate()
71
72
lddfm.foldersOnTop = function(floop,path)
73
	local output = {}
74
	for a = 1, #floop do
75
		if fs.isDir(fs.combine(path,floop[a])) then
76
			table.insert(output,1,floop[a])
77
		else
78
			table.insert(output,floop[a])
79
		end
80
	end
81
	return output
82
end
83
84
lddfm.filterFileFolders = function(list,path,_noFiles,_noFolders,_noCD,_doHidden)
85
	local output = {}
86
	for a = 1, #list do
87
		local entry = fs.combine(path,list[a])
88
		if fs.isDir(entry) then
89
			if entry == ".." then
90
				if not (_noCD or _noFolders) then table.insert(output,list[a]) end
91
			else
92
				if not ((not _doHidden) and list[a]:sub(1,1) == ".") then
93
					if not _noFolders then table.insert(output,list[a]) end
94
				end
95
			end
96
		else
97
			if not ((not _doHidden) and list[a]:sub(1,1) == ".") then
98
				if not _noFiles then table.insert(output,list[a]) end
99
			end
100
		end
101
	end
102
	return output
103
end
104
105
lddfm.isColor = function(col)
106
	for k,v in pairs(colors) do
107
		if v == col then
108
			return true, k
109
		end
110
	end
111
	return false
112
end
113
114
term.clearLine = function(x1,x2,_y,_bg,_char) --this doesn't break anything, I swear!!
115
	local cbg, bg = term.getBackgroundColor()
116
	local x,y = term.getCursorPos()
117
	local sx,sy = term.getSize()
118
	if type(_char) == "string" then char = _char else char = " " end
119
	if type(_bg) == "number" then
120
		if lddfm.isColor(_bg) then bg = _bg
121
		else bg = cbg end
122
	else bg = cbg end
123
	term.setCursorPos(x1 or 1, _y or y)
124
	term.setBackgroundColor(bg)
125
	if x2 then --it pains me to add an if statement to something as simple as this
126
		term.write((char or " "):rep(x2-x1))
127
	else
128
		term.write((char or " "):rep(sx-(x1 or 0)))
129
	end
130
	term.setBackgroundColor(cbg)
131
	term.setCursorPos(x,y)
132
end
133
134
lddfm.render = function(_x1,_y1,_x2,_y2,_rlist,_path,_rscroll,_canClose,_scrbarY)
135
	local tsv = term.current().setVisible
136
	local px,py = term.getCursorPos()
137
	if tsv then tsv(false) end
138
	local x1, x2, y1, y2 = _x1 or 1, _x2 or lddfm.scr_x, _y1 or 1, _y2 or lddfm.scr_y
139
	local rlist = _rlist or {"Invalid directory."}
140
	local path = _path or "And that's terrible."
141
	ypaths = {}
142
	local rscroll = _rscroll or 0
143
	for a = y1, y2 do
144
		term.clearLine(x1,x2,a,lddfm.p.bg)
145
	end
146
	term.setCursorPos(x1,y1)
147
	term.setTextColor(lddfm.p.p_txt)
148
	term.clearLine(x1,x2+1,y1,lddfm.p.p_bg)
149
	term.setBackgroundColor(lddfm.p.p_bg)
150
	term.write(("/"..path):sub(1,x2-x1))
151
	for a = 1,(y2-y1) do
152
		if rlist[a+rscroll] then
153
			term.setCursorPos(x1,a+(y1))
154
			if fs.isDir(fs.combine(path,rlist[a+rscroll])) then
155
				term.clearLine(x1,x2,a+(y1),lddfm.p.d_bg)
156
				term.setTextColor(lddfm.p.d_txt)
157
				term.setBackgroundColor(lddfm.p.d_bg)
158
			else
159
				term.clearLine(x1,x2,a+(y1),lddfm.p.f_bg)
160
				term.setTextColor(lddfm.p.f_txt)
161
				term.setBackgroundColor(lddfm.p.f_bg)
162
			end
163
			term.write(rlist[a+rscroll]:sub(1,x2-x1))
164
			ypaths[a+(y1)] = rlist[a+rscroll]
165
		else
166
			term.clearLine(x1,x2,a+(y1),lddfm.p.bg)
167
		end
168
	end
169
	local scrbarY = _scrbarY or math.ceil( (y1+1)+( (_rscroll/(#_rlist-(y2-(y1+1))))*(y2-(y1+1)) ) )
170
	for a = y1+1, y2 do
171
		term.setCursorPos(x2,a)
172
		if a == scrbarY then
173
			term.setBackgroundColor(lddfm.p.scrbar)
174
		else
175
			term.setBackgroundColor(lddfm.p.scr)
176
		end
177
		term.write(" ")
178
	end
179
	if _canClose then
180
		term.setCursorPos(x2-4,y1)
181
		term.setTextColor(lddfm.p.close_txt)
182
		term.setBackgroundColor(lddfm.p.close_bg)
183
		term.write("close")
184
	end
185
	term.setCursorPos(px,py)
186
	if tsv then tsv(true) end
187
	return scrbarY
188
end
189
190
lddfm.coolOutro = function(x1,y1,x2,y2,_bg,_txt,char)
191
	local cx, cy = term.getCursorPos()
192
	local bg, txt = term.getBackgroundColor(), term.getTextColor()
193
	term.setTextColor(_txt or colors.white)
194
	term.setBackgroundColor(_bg or colors.black)
195
	local _uwah = 0
196
	for y = y1, y2 do
197
		for x = x1, x2 do
198
			_uwah = _uwah + 1
199
			term.setCursorPos(x,y)
200
			term.write(char or " ")
201
			if _uwah >= math.ceil((x2-x1)*1.63) then sleep(0) _uwah = 0 end
202
		end
203
	end
204
	term.setTextColor(txt)
205
	term.setBackgroundColor(bg)
206
	term.setCursorPos(cx,cy)
207
end
208
209
lddfm.scrollMenu = function(amount,list,y1,y2)
210
	if #list >= y2-y1 then
211
		lddfm.scroll = lddfm.scroll + amount
212
		if lddfm.scroll < 0 then
213
			lddfm.scroll = 0
214
		end
215
		if lddfm.scroll > #list-(y2-y1) then
216
			lddfm.scroll = #list-(y2-y1)
217
		end
218
	end
219
end
220
221
--[[
222
 a quick explanation of the arguments:
223
224
x1 and y1: top-left corner coordinates of menu window. defaults to the top-left corner of the screen
225
x2 and y2: bottom-right corner coordinates of menu window. defaults to the bottom-right corner of the screen
226
_path: path to start viewing. defaults to "/"
227
_noFiles: whether or not to view files in the menu, mainly for picking a path for installing something. defaults to false
228
_noFolders: whether or not to view folders in the menu, mainly for choosing a file to run or whatever. defaults to false
229
_noCD: whether or not you can change the directory, mainly to limit choices to a single folder. defaults to false
230
_noSelectFolders: whether or not you can select folders to return. defaults to false
231
_doHidden: whether or not to hide hidden files (starts with "."). defaults to false
232
_p: the palate. has: bg, d_txt, d_bg, f_txt, t_bg, p_txt, p_bg, scr, scrbar. 'd' is for directory, 'f' is for file, 'p' is for path bar.
233
_canClose: whether or not you can click on the little top-right "Cancel" button.
234
--]]
235
236
local makeMenu = function(_x1,_y1,_x2,_y2,_path,_noFiles,_noFolders,_noCD,_noSelectFolders,_doHidden,_p,_canClose)
237
	if _noFiles and _noFolders then
238
		return false, "C'mon, man..."
239
	end
240
	if _x1 == true then
241
		return false, "arguments: x1, y1, x2, y2, path, noFiles, noFolders, noCD, noSelectFolders, doHidden, palate, canClose" -- a little help
242
	end
243
	lddfm.setPalate(_p)
244
	local path, list = _path or ""
245
	lddfm.scroll = 0
246
	local _pbg, _ptxt = term.getBackgroundColor(), term.getTextColor()
247
	local x1, x2, y1, y2 = _x1 or 1, _x2 or lddfm.scr_x, _y1 or 1, _y2 or lddfm.scr_y
248
	local keysDown = {}
249
	local _barrY
250
	while true do
251
		list = lddfm.foldersOnTop(lddfm.filterFileFolders(fs.list(path),path,_noFiles,_noFolders,_noCD,_doHidden),path)
252
		if (fs.getDir(path) ~= "..") and not (_noCD or _noFolders) then
253
			table.insert(list,1,"..")
254
		end
255
		_res, _barrY = pcall( function() return lddfm.render(x1,y1,x2,y2,list,path,lddfm.scroll,_canClose) end)
256
		if not _res then
257
			local tsv = term.current().setVisible
258
			if tsv then tsv(true) end
259
			error(_barrY)
260
		end
261
		local evt = {os.pullEvent()}
262
		if evt[1] == "mouse_scroll" then
263
			lddfm.scrollMenu(evt[2],list,y1,y2)
264
		elseif evt[1] == "mouse_click" then
265
			local butt,mx,my = evt[2],evt[3],evt[4]
266
			if (butt == 1 and my == y1 and mx <= x2 and mx >= x2-4) and _canClose then
267
				--lddfm.coolOutro(x1,y1,x2,y2)
268
				term.setTextColor(_ptxt) term.setBackgroundColor(_pbg)
269
				return false
270
			elseif ypaths[my] and (mx >= x1 and mx < x2) then --x2 is reserved for the scrollbar, breh
271
				if fs.isDir(fs.combine(path,ypaths[my])) then
272
					if _noCD or butt == 3 then
273
						if not _noSelectFolders or _noFolders then
274
							--lddfm.coolOutro(x1,y1,x2,y2)
275
							term.setTextColor(_ptxt) term.setBackgroundColor(_pbg)
276
							return fs.combine(path,ypaths[my])
277
						end
278
					else
279
						path = fs.combine(path,ypaths[my])
280
						lddfm.scroll = 0
281
					end
282
				else
283
					term.setTextColor(_ptxt) term.setBackgroundColor(_pbg)
284
					return fs.combine(path,ypaths[my])
285
				end
286
			end
287
		elseif evt[1] == "key" then
288
			keysDown[evt[2]] = true
289
			if evt[2] == keys.enter and not (_noFolders or _noCD or _noSelectFolders) then --the logic for _noCD being you'd normally need to go back a directory to select the current directory.
290
				--lddfm.coolOutro(x1,y1,x2,y2)
291
				term.setTextColor(_ptxt) term.setBackgroundColor(_pbg)
292
				return path
293
			end
294
			if evt[2] == keys.up then
295
				lddfm.scrollMenu(-1,list,y1,y2)
296
			elseif evt[2] == keys.down then
297
				lddfm.scrollMenu(1,list,y1,y2)
298
			end
299
			if evt[2] == keys.pageUp then
300
				lddfm.scrollMenu(y1-y2,list,y1,y2)
301
			elseif evt[2] == keys.pageDown then
302-
	itPath = ""
302+
				lddfm.scrollMenu(y2-y1,list,y1,y2)
303
			end
304-
		term.setCursorPos(1,6)
304+
			if evt[2] == keys.home then
305-
		term.setTextColor(colors.black)
305+
				lddfm.scroll = 0
306-
		term.setBackgroundColor(colors.lightGray)
306+
			elseif evt[2] == keys["end"] then
307-
		term.clearLine()
307+
				if #list > (y2-y1) then
308-
		write(">")
308+
					lddfm.scroll = #list-(y2-y1)
309
				end
310-
		itPath = read()
310+
311-
	until string.gsub(itPath," ","") ~= ""
311+
			if evt[2] == keys.h then
312
				if keysDown[keys.leftCtrl] or keysDown[keys.rightCtrl] then
313
					_doHidden = not _doHidden
314
				end
315
			end
316
		elseif evt[1] == "key_up" then
317
			keysDown[evt[2]] = false
318
		end
319
	end
320
end
321
322
323
local defaultKey = "swordfish" --the most secure.
324
local tArg = {...}
325
local mode, itPath, idfilter, enckey = tArg[1], tArg[2], tonumber(tArg[3]), tArg[4], tArg[5]
326
filetree = {}
327
if not enckey then
328
	enckey = defaultKey
329
end
330
if tArg[5] == "y" then
331
	doReadOnly = true
332
else
333
	doReadOnly = false
334
end
335
336
--API made by valithor.
337
local encrypt = function(msg,key)
338
	local num = ""
339
	for i = 1, #key do
340
		local let = key:sub(i,i):byte()
341
		num = let <= 9  and num.."99"..let or let<=99 and num.."9"..let or num..let
342
		num = #msg..num
343
	end
344
	math.randomseed(tonumber(num))
345
	local encrypt = ""
346
	for i = 1, #msg do
347
		local rotation = math.random(0,94)
348
		local byte = msg:sub(i,i):byte()
349
		local rotate = rotation+byte <= 127 and rotation +byte or ((rotation+byte)%127)+32
350
		encrypt = encrypt..string.char(rotate)
351
	end
352
	return encrypt
353
end
354
355
local decrypt = function(msg,key)
356
	local num = ""
357
	for i = 1, #key do
358
		local let = key:sub(i,i):byte()
359
		num = let <= 9 and num.."99"..let or let<=99 and num.."9"..let or num..let
360
		num = #msg..num
361
	end
362
	math.randomseed(tonumber(num))
363
	local decrypt = ""
364
	for i = 1, #msg do
365-
	drawThing("Save as what? (optional)",3)
365+
366-
	itPath = nil
366+
367
		local rotate = byte-rotation >= 32 and byte-rotation or byte-rotation
368
		if rotate < 32 then
369
			rotate = rotate+95
370
		end
371
		decrypt = decrypt..string.char(rotate)
372
	end
373-
	itPath = read()
373+
374
end
375
376
local tEnc = function(msg)
377
	return encrypt(encrypt(tostring(msg),enckey),tostring(math.floor(os.time()/2)))
378
end
379
local tDec = function(msg)
380
	return decrypt(decrypt(tostring(msg),enckey),tostring(math.floor(os.time()/2)))
381
end
382
383
listAll = function(_path, _files, noredundant) --Thanks Lyqyd!
384
	local path = _path or ""
385
	local files = _files or {}
386
	if #path > 1 then table.insert(files, path) end
387
	for _, file in ipairs(fs.list(path)) do
388
		local path = fs.combine(path, file)
389
		if fs.isDir(path) then
390
			listAll(path, files)
391
		else
392
			table.insert(files, path)
393
		end
394
	end
395
	if noredundant then
396
		for a = 1, #files do
397
			if fs.isDir(tostring(files[a])) then
398
				if #fs.list(tostring(files[a])) ~= 0 then
399
					table.remove(files,a)
400
				end
401
			end
402
		end
403
	end
404
	return files
405
end
406
407
local function choice(input)
408
	local event, button
409
	repeat
410
		event, button = os.pullEvent("key")
411
		if type(button) == "number" then button = keys.getName(button) end
412
		if button == nil then button = " " end
413
	until string.find(input, button)
414
	return button
415
end
416
417
local drawThing = function(text,y,t,b)
418
	local scr_x, scr_y = term.getSize()
419
	local _pt,_pb = term.getTextColor(), term.getBackgroundColor()
420
	if t then term.setTextColor(t) else term.setTextColor(colors.black) end
421
	if b then term.setBackgroundColor(b) else term.setBackgroundColor(colors.white) end
422
	term.setCursorPos(1,y-1)
423
	term.clearLine()
424
	term.setCursorPos((scr_x/2)-(#text/2),y)
425
	term.clearLine()
426
	print(text)
427
	term.clearLine()
428
	term.setTextColor(_pt)
429
	term.setBackgroundColor(_pb)
430
end
431
432
output = {}
433
434
local send = function()
435
	if not fs.exists(itPath) then
436
		error("No such file.")
437
	end
438
	contents = {}
439
	rawContents = {}
440
	if not fs.isDir(itPath) then
441
		local file = fs.open(itPath,"r")
442
		line = ""
443
		local s = 0
444
		while line do
445
			line = file.readLine()
446
			if line then
447
				table.insert(rawContents,fixstr(line))
448
				table.insert(contents,tEnc(fixstr(line)))
449
				if s >= 64 then
450
					yield()
451
					s = 0
452
				else
453
					s = s + 1
454
				end
455
			end
456
		end
457
		filetree = {[fs.getName(itPath)] = {fyle = contents, dir = false}}
458
		file.close()
459
		output = {id = os.getComputerID(), files = filetree}
460
	else
461
		filelist = {}
462
		_filelist = listAll(itPath,nil,true)
463
		if not doReadOnly then
464
			for a = 1, #_filelist do
465
				if not fs.isReadOnly(_filelist[a]) then
466
					table.insert(filelist,_filelist[a])
467
				end
468
			end
469
		else
470
			filelist = _filelist
471
		end
472
		for a = 1, #filelist do
473
			local isDir
474
			contents = {}
475
			rawContents = {}
476
			if not fs.isDir(filelist[a]) then
477
				local file = fs.open(filelist[a],"r")
478
				local line = ""
479
				local s = 0
480
				while line do
481
					line = file.readLine()
482
					if line then
483
						table.insert(contents,tEnc(fixstr(line)))
484
						table.insert(rawContents,fixstr(line))
485
						if s >= 64 then
486
							yield()
487
							s = 0
488
						else
489
							s = s + 1
490
						end
491
					end
492
				end
493
				file.close()
494
				isDir = false
495
			else
496
				contents = {""}
497
				isDir = true
498
			end
499
			if fs.combine("",shell.resolve(itPath)) == "" then --This oughta fix things
500
				filelist[a] = fs.combine("root"..os.getComputerID(),filelist[a])
501
			end
502
			filetree[filelist[a]] = {fyle = contents, dir = isDir}
503
		end
504
		output = {id = os.getComputerID(), files = filetree}
505
	end
506
	modem.transmit(channel,channel,output)
507
end
508
local receive = function(GUImode)
509
	local combinedSize = 0
510
	local filecount = 0
511
	--local event, side, sendID, repChannel, msg
512
	while true do
513
		input = {}
514
		event, side, sendChannel, repChannel, msg = os.pullEvent()
515
		if event == "char" and string.lower(side) == "x" then
516
			if not GUImode then
517
				print("Cancelled.")
518
			end
519
			return 0,0,false
520
		end
521
		if type(msg) == "table" then
522
			if type(msg.files) == "table" and (idfilter or msg.id) == msg.id then
523
				if GUImode then
524
					term.setBackgroundColor(colors.gray)
525
					term.clear()
526
					drawThing("Decrypting...",3)
527
				else
528
					print("Decrypting...")
529
				end
530
				break
531
			end
532
		end
533
	end
534
	for k,v in pairs(msg.files) do
535
		local fee
536
		if not itPath then
537
			fee = k
538
		else
539
			local slashpos = string.find(k,"/") or 1
540
			fee = fs.combine(itPath,k:sub(slashpos))
541
		end
542
		local doOverwrite = true
543
		if fs.exists(fee) and fee == k then
544
			if GUImode then
545
				drawThing("Overwrite '"..fee.."'? [Y/N]",6)
546
			else
547
				print("Overwrite '"..fee.."'? [Y/N]")
548
			end
549
			if choice("yn") == "n" then
550
				doOverwrite = false
551
			else
552
				doOverwrite = true
553
			end
554
		end
555
		if doOverwrite then
556
			filecount = filecount + 1
557
			if not fs.exists(fs.getDir(fee)) then fs.makeDir(fs.getDir(fee)) end
558
			if type(v) == "table" then
559
				if v.dir then
560
					fs.makeDir(fee)
561
				else
562
					local file = fs.open(fee,"w")
563
					if file then
564
						for a = 1, #v.fyle do
565
							file.writeLine(fixstr(tDec(v.fyle[a])))
566
							if a % 32 == 0 then
567
								yield()
568
							end
569
						end
570
						file.close()
571
						combinedSize = combinedSize + fs.getSize(fee)
572
					end
573
				end
574
			end
575
		end
576
	end
577
	return filecount, combinedSize, true
578
end
579
580
local sendGUI = function()
581
	term.setBackgroundColor(colors.gray)
582
	term.clear()
583
	drawThing("Which file/folder?",3)
584
	itPath = makeMenu(1,5,_,_,_,_,_,_,_,_,_,true)
585
	term.setTextColor(colors.white)
586
	term.setBackgroundColor(colors.gray)
587
	if itPath == false then
588
		return false
589
	end
590
	if not fs.exists(itPath) then 
591
		drawThing("Doesn't exist!",3)
592
		sleep(0.6)
593
		return false
594
	end
595
	term.clear()
596
	drawThing("Encryption key? (optional)",3)
597
	enckey = nil
598
	term.setCursorPos(1,6)
599
	term.setTextColor(colors.black)
600
	term.setBackgroundColor(colors.lightGray)
601
	term.clearLine()
602
	write(">")
603
	sleep(0)
604
	enckey = read("*")
605
	if enckey == "" then enckey = defaultKey end
606
	drawThing("ID filter? (optional)",3)
607
	idfilter = nil
608
	term.setCursorPos(1,6)
609
	term.setTextColor(colors.black)
610
	term.setBackgroundColor(colors.lightGray)
611
	term.clearLine()
612
	write(">")
613
	sleep(0)
614
	idfilter = tonumber(read())
615
	drawThing("Do read-only files/folders? (Y/N)",3)
616
	doReadOnly = false
617
	term.setCursorPos(1,6)
618
	term.setTextColor(colors.black)
619
	term.setBackgroundColor(colors.lightGray)
620
	term.clearLine()
621
	sleep(0)
622
	local thing = choice("yn")
623
	if thing == "y" then doReadOnly = true else doReadOnly = false end
624
	local thang = "Encrypting"
625
	if idfilter then
626
		thang = thang.." for ID "..tostring(idfilter).."..."
627
	else
628
		thang = thang.."..."
629
	end
630
	term.setBackgroundColor(colors.gray)
631
	term.clear()
632
	drawThing(thang,3)
633
	send()
634
	drawThing("Sent '"..itPath.."'!",3)
635
	sleep(0)
636
	return true
637
end
638
639
local receiveGUI = function()
640
	term.setBackgroundColor(colors.gray)
641
	term.clear()
642
	drawThing("Save in what folder?",3)
643
	itPath = makeMenu(1,5,_,_,_,true,_,_,_,_,_,true)
644
	term.clear()
645
	drawThing("Name file? (optional)",3)
646
	term.setCursorPos(1,6)
647
	term.setTextColor(colors.black)
648
	term.setBackgroundColor(colors.lightGray)
649
	term.clearLine()
650
	write(">")
651
	sleep(0)
652
	itPath = fs.combine(itPath,read())
653
	if string.gsub(itPath," ","") == "" then
654
		itPath = nil
655
	end
656
	drawThing("Decryption key? (optional)",3)
657
	enckey = nil
658
	term.setCursorPos(1,6)
659
	term.setTextColor(colors.black)
660
	term.setBackgroundColor(colors.lightGray)
661
	term.clearLine()
662
	write(">")
663
	sleep(0)
664
	enckey = read("*")
665
	if enckey == "" then enckey = defaultKey end
666
	drawThing("Filter ID? (optional)",3)
667
	idfilter = nil
668
	term.setCursorPos(1,6)
669
	term.setTextColor(colors.black)
670
	term.setBackgroundColor(colors.lightGray)
671
	term.clearLine()
672
	write(">")
673
	sleep(0)
674
	idfilter = tonumber(read())
675
	local thang = "Receiving"
676
	if idfilter then
677
		thang = thang.." from ID "..tostring(idfilter).."..."
678
	else
679
		thang = thang.."..."
680
	end
681
	term.setBackgroundColor(colors.gray)
682
	term.clear()
683
	drawThing(thang,3)
684
	local count,size,success = receive(true)
685
	if success then
686
		drawThing("Received!",3)
687
		if count ~= 1 then
688
			drawThing("(Got "..count.." files)",5)
689
		else
690
			drawThing("(Got "..count.." file)",5)
691
		end
692
		if size ~= 1 then
693
			drawThing("(Totals "..size.." bytes)",7)
694
		else
695
			drawThing("(Totals "..size.." byte)",7)
696
		end
697
	else
698
		drawThing("Cancelled.",3)
699
	end
700
	sleep(0)
701
	return true
702
end
703
704
local gui = function()
705
	local scr_x, scr_y = term.getSize()
706
	local prevColor = term.getBackgroundColor()
707
	local evt = {}
708
	term.setBackgroundColor(colors.gray)
709
	term.clear()
710
	while true do
711
		term.setBackgroundColor(colors.gray)
712
		if res then term.clear() end
713
		drawThing("Whisk BETA",3)
714
		drawThing("(1) Send",7,colors.white,colors.black)
715
		drawThing("(2) Receive",11,colors.white,colors.black)
716
		drawThing("(X,Q) Exit",15,colors.white,colors.black)
717
		evt = {os.pullEvent()}
718
		local res = false
719
		sleep(0)
720
		if evt[1] == "mouse_click" then
721
			if evt[2] == 1 then
722
				if math.abs(evt[4] - 7) <= 1 then
723
					res = sendGUI()
724
				elseif math.abs(evt[4] - 11) <= 1 then
725
					res = receiveGUI()
726
				elseif math.abs(evt[4] - 15) <= 1 then
727
					res = true
728
				end
729
			end
730
		elseif evt[1] == "key" then
731
			if evt[2] == keys.one then
732
				res = sendGUI()
733
			elseif evt[2] == keys.two then
734
				res = receiveGUI()
735
			elseif evt[2] == keys.three or evt[2] == keys.q or evt[2] == keys.x then
736
				res = true
737
			end
738
		end
739
		if res then
740
			term.setCursorPos(1,scr_y)
741
			term.setBackgroundColor(prevColor)
742
			term.clearLine()
743
			break
744
		else
745
			term.setBackgroundColor(colors.gray)
746
			term.clear()
747
		end
748
	end
749
end
750
751
if modem then modem.open(channel) end
752
753
waitForModem = function()
754
	while true do
755
		sleep(0)
756
		modem = peripheral.find("modem")
757
		if modem then
758
			return
759
		end
760
	end
761
end
762
763
if not tArg[1] then
764
	local prevBG, prevTXT = term.getBackgroundColor(), term.getTextColor()
765
	if modem then
766
		gui()
767
	else
768
		term.setBackgroundColor(colors.gray)
769
		term.clear()
770
		drawThing("You don't have a modem!",3)
771
		drawThing("Attach one or press a key.",5)
772
		sleep(0.1)
773
		local outcome = parallel.waitForAny(function() os.pullEvent("key") end, waitForModem)
774
		if modem then
775
			modem.open(channel)
776
			gui()
777
		else
778
			local scr_x,scr_y = term.getSize()
779
			term.setCursorPos(1,scr_y)
780
			term.setBackgroundColor(prevBG)
781
			term.setTextColor(prevTXT)
782
			term.clearLine()
783
			sleep(0)
784
			return false
785
		end
786
	end	
787
else
788
	if not modem then
789
		error("No modem detected.")
790
	end
791
	if mode == "send" then
792
		send()
793
	elseif mode == "receive" then
794
		write("Receiving")
795
		if idfilter then
796
			print(" from "..idfilter.."...")
797
		else
798
			print("...")
799
		end
800
		local fc, size = receive(false)
801
		write("Done. (got "..fc.." file")
802
		if fc ~= 1 then write("s") end
803
		write(", totalling "..size.." byte")
804
		if size ~= 1 then print("s)") else print(")") end
805
	else
806
		displayHelp()
807
	end
808
end
809
810
sleep(0)