View difference between Paste ID: my79ZLZb and XDgeSDTq
SHOW: | | - or go back to the newest paste.
1
--[[
2
   Sinelock v1.3
3
  The *COOLEST* computer/door lock ever!
4
 Now with slightly less seizure!
5
6-
 pastebin get XDgeSDTq sinelock
6+
 pastebin get my79ZLZb slb
7-
 std pb XDgeSDTq sinelock
7+
 std pb my79ZLZb slb
8
 std ld sinelock sinelock
9
10
 Now with salting!
11
--]]
12
local scr_x, scr_y = term.getSize()	--Gets screen size. Don't modify this
13
14
--Config variables start!
15
local terminateMode = 2				--0 enables termination, 1 blocks it, 2 provides a taunting screen.
16
local passFile = ".sl_password"		--The ABSOLUTE path of the password file.
17
local saltFile = ".sl_salt"			--The ABSOLUTE path of the salt file.
18
local characterLimit = 1024			--The cap of characters at the read() prompt. Set this to prevent crashes.
19
local runProgram = ""				--Set to something to run it when correct, and not using doors.
20
local dahChar = "*"					--The character used to hide characters when typed.
21
local doKeyCards = true				--Whether or not the lock also accepts keycards (floppy disks) as well as passwords.
22-
local doEjectDisk = false			--Whether or not to eject a keycard after it's accepted, just to speed things up a bit.
22+
local doEjectDisk = true			--Whether or not to eject a keycard after it's accepted, just to speed things up a bit.
23
local doorSides = {}				--If it has anything, the lock will open the doors instead of unlocking the PC.
24
local doInvertSignal = false		--If true, it will invert the redstone signal of the door, in case you need to.
25
local doShowDoorSides = true		--If true, will show the door sides being opened. Set to false if you are paranoid.
26
local beWavey = true				--Whether or not to animate the sine wave.
27
local readYpos = scr_y-2			--The Y position of the read() prompt
28
local requireAllPasswords = false	--Whether or not the lock asks for ONE of the multiple passwords, or ALL of them in order.
29
local badlength = 4					--The length in seconds that you have to wait to try again.
30
local goodlength = 6				--The length in seconds that doors will stay open.
31
local sineFrameDelay = 0.15			--The amount of time between sine animation frames. Tradeoff of purty vs performance.
32
local palate = {
33
	frontsine = colors.lightGray,
34
	backsine = colors.gray,
35
	background = colors.black,
36
	rainColor = colors.gray,
37
	rainChar = "|",
38
	promptBG = colors.gray,
39
	promptTXT = colors.white,
40
	wrongBG = colors.black,
41
	wrongTXT = colors.gray,
42
}
43
local language = "english"
44
local lang = {
45
	english = {
46
		wrong1 = "YOU ARE WRONG.",
47
		wrong2 = "YOU ARE WRONG. AS ALWAYS.",
48
		right1 = "Correct!",
49
		right2 = "Correct, finally!",
50
	},
51
	spanish = {
52
		wrong1 = "ESTA USTED EQUIVOCADO.",
53
		wrong2 = "ESTA USTED EQUIVOCADO. TODAVIA OTRA VEZ.",
54
		right1 = "Correcto!",
55
		right2 = "Asi es, por fin!",
56
		noTerminate = "No termine!",
57
	},
58
	german = {
59
		wrong1 = "SIE LIEGEN FALSCH.",
60
		wrong2 = "SIE LIEGEN FALSCH. WIE IMMER.",
61
		right1 = "Richtig!",
62
		right2 = "Richtig, endlich!",
63
		noTerminate = "Nicht zu beenden!",
64
	},
65
	dutch = {
66
		wrong1 = "U BENT ONJUIST.",
67
		wrong2 = "JE BENT ONJUIST, ALS ALTIJD.",
68
		right1 = "Dat is juist!",
69
		right2 = "Dat is juist, eindelijk!",
70
		noTerminate = "Niet te beeindigen!",
71
	},
72
	latin = { --As a joke
73
		wrong1 = "ERRAS",
74
		wrong2 = "TU DEFICIENTES!",
75
		right1 = "Quod suus 'verum!",
76
		right2 = "Quod suus 'verum, demum!",
77
		noTerminate = "Vade futuo te ipsum!",
78
	},
79
	italian = {
80
		wrong1 = "HAI SBAGLIATO.",
81
		wrong2 = "HAI SBAGLIATO, COME SEMPRE D'ALTRONDE.",
82
		right1 = "CORRETTO!",
83
		right2 = "CORRETTO, FINALMENTE!",
84
		noTerminate = "Non cercare di terminarmi",
85
	},
86
}
87
88
-- Config variables end. Don't touch anything else, m'kay?
89
if not _VERSION then
90
	return printError("Sorry, only CC 1.7 and later supported.")
91
end
92
local csv, salt, doSine
93
local floor, ceil, random, abs = math.floor, math.ceil, math.random, math.abs
94
local sin, cos = math.sin, math.cos
95
local rhite = term.write
96
local setTextColor, setBackgroundColor, getTextColor, getBackgroundColor = term.setTextColor, term.setBackgroundColor, term.getTextColor, term.getBackgroundColor
97
local setCursorPos, setCursorBlink, getCursorPos, getSize = term.setCursorPos, term.setCursorBlink, term.getCursorPos, term.getSize
98
local sineLevel = 1
99
local isTerminable = false
100
local kaykaycoolcool = true
101
if term.current().setVisible then
102
	csv = true
103
else
104
	csv = false
105
end
106
107
local writeError = function(...)
108
	local tx,bg = getTextColor(),getBackgroundColor()
109
	if term.isColor() then
110
		setTextColor(colors.red)
111
	else
112
		setTextColor(colors.white)
113
	end
114
	rhite(table.concat(arg," "))
115
	setTextColor(tx)
116
	setBackgroundColor(bg)
117
end
118
119
local goodPullEvent
120
if terminateMode == 1 then
121
	if os.pullEvent ~= os.pullEventRaw then
122
		goodPullEvent = os.pullEvent
123
	end
124
	os.pullEvent = os.pullEventRaw
125
end
126
127
local keepLooping = true
128
129
---- SHA256 START ----
130
--SHA256 implementation done by GravityScore.
131
132
local MOD = 2^32
133
local MODM = MOD-1
134
135
local function memoize(f)
136
	local mt = {}
137
	local t = setmetatable({}, mt)
138
	function mt:__index(k)
139
		local v = f(k)
140
		t[k] = v
141
		return v
142
	end
143
	return t
144
end
145
146
local function make_bitop_uncached(t, m)
147
	local function bitop(a, b)
148
		local res,p = 0,1
149
		while a ~= 0 and b ~= 0 do
150
			local am, bm = a % m, b % m
151
			res = res + t[am][bm] * p
152
			a = (a - am) / m
153
			b = (b - bm) / m
154
			p = p*m
155
		end
156
		res = res + (a + b) * p
157
		return res
158
	end
159
	return bitop
160
end
161
162
local function make_bitop(t)
163
	local op1 = make_bitop_uncached(t,2^1)
164
	local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)
165
	return make_bitop_uncached(op2, 2 ^ (t.n or 1))
166
end
167
168
local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
169
170
local function bxor(a, b, c, ...)
171
	local z = nil
172
	if b then
173
		a = a % MOD
174
		b = b % MOD
175
		z = bxor1(a, b)
176
		if c then z = bxor(z, c, ...) end
177
		return z
178
	elseif a then return a % MOD
179
	else return 0 end
180
end
181
182
local function band(a, b, c, ...)
183
	local z
184
	if b then
185
		a = a % MOD
186
		b = b % MOD
187
		z = ((a + b) - bxor1(a,b)) / 2
188
		if c then z = bit32_band(z, c, ...) end
189
		return z
190
	elseif a then return a % MOD
191
	else return MODM end
192
end
193
194
local function bnot(x) return (-1 - x) % MOD end
195
196
local function rshift1(a, disp)
197
	if disp < 0 then return lshift(a,-disp) end
198
	return floor(a % 2 ^ 32 / 2 ^ disp)
199
end
200
201
local function rshift(x, disp)
202
	if disp > 31 or disp < -31 then return 0 end
203
	return rshift1(x % MOD, disp)
204
end
205
206
local function lshift(a, disp)
207
	if disp < 0 then return rshift(a,-disp) end 
208
	return (a * 2 ^ disp) % 2 ^ 32
209
end
210
211
local function rrotate(x, disp)
212
    x = x % MOD
213
    disp = disp % 32
214
    local low = band(x, 2 ^ disp - 1)
215
    return rshift(x, disp) + lshift(low, 32 - disp)
216
end
217
218
local k = {
219
	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
220
	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
221
	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
222
	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
223
	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
224
	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
225
	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
226
	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
227
	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
228
	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
229
	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
230
	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
231
	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
232
	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
233
	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
234
	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
235
}
236
237
local function str2hexa(s)
238
	return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end))
239
end
240
241
local function num2s(l, n)
242
	local s = ""
243
	for i = 1, n do
244
		local rem = l % 256
245
		s = string.char(rem) .. s
246
		l = (l - rem) / 256
247
	end
248
	return s
249
end
250
251
local function s232num(s, i)
252
	local n = 0
253
	for i = i, i + 3 do n = n*256 + string.byte(s, i) end
254
	return n
255
end
256
257
local function preproc(msg, len)
258
	local extra = 64 - ((len + 9) % 64)
259
	len = num2s(8 * len, 8)
260
	msg = msg .. "\128" .. string.rep("\0", extra) .. len
261
	assert(#msg % 64 == 0)
262
	return msg
263
end
264
265
local function initH256(H)
266
	H[1] = 0x6a09e667
267
	H[2] = 0xbb67ae85
268
	H[3] = 0x3c6ef372
269
	H[4] = 0xa54ff53a
270
	H[5] = 0x510e527f
271
	H[6] = 0x9b05688c
272
	H[7] = 0x1f83d9ab
273
	H[8] = 0x5be0cd19
274
	return H
275
end
276
277
local function digestblock(msg, i, H)
278
	local w = {}
279
	for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end
280
	for j = 17, 64 do
281
		local v = w[j - 15]
282
		local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
283
		v = w[j - 2]
284
		w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
285
	end
286
287
	local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
288
	for i = 1, 64 do
289
		local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
290
		local maj = bxor(band(a, b), band(a, c), band(b, c))
291
		local t2 = s0 + maj
292
		local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
293
		local ch = bxor (band(e, f), band(bnot(e), g))
294
		local t1 = h + s1 + ch + k[i] + w[i]
295
		h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
296
	end
297
298
	H[1] = band(H[1] + a)
299
	H[2] = band(H[2] + b)
300
	H[3] = band(H[3] + c)
301
	H[4] = band(H[4] + d)
302
	H[5] = band(H[5] + e)
303
	H[6] = band(H[6] + f)
304
	H[7] = band(H[7] + g)
305
	H[8] = band(H[8] + h)
306
end
307
308
local function sha256(...)
309
	local msg = table.concat(arg,",")
310
	msg = preproc(msg, #msg)
311
	local H = initH256({})
312
	for i = 1, #msg, 64 do digestblock(msg, i, H) end
313
	return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
314
		num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
315
end
316
317
---- SHA256 END ----
318
319
local terminates = 0
320
local sillyTerminate = function()
321
	local goodpull = _G.os.pullEvent
322
	os.pullEvent = os.pullEventRaw
323
	terminates = terminates + 1
324
	local script = {
325
		"You shall not pass!",
326
		"THOU shalt not pass!",
327
		"Stop trying to pass!",
328
		"...maybe I'm not clear.",
329
		"YOU. SHALL NOT. PASS!!",
330
		"Pass thou shalt not!",
331
		"Hey, piss off, will ya?",
332
		"I haven't got all day.",
333
		"...no, shut up. I don't.",
334
		"I won't tell you it!",
335
		"No password for you.",
336
		"It's been hashed!",
337
		"Hashed...with a salt!",
338
		"I'll never tell you the salt.",
339
		"You know why?",
340
		"Because that requires passing!",
341
		"WHICH THOU SHALT NOT DO!",
342
		"(oh btw don't pass k?)",
343
		"You! Don't pass!",
344
		"That means YOU!",
345
		"Cut it out!",
346
		"Re: Cut it out!",
347
		"Perhaps if you keep it up...",
348
		"..hmm...",
349
		"..oh I give up.",
350
		"<bullshitterm>",
351
		"What? Is this what you wanted?",
352
		"Huh? No? I-it's not?",
353
		"Well then...!",
354
		"<toobad>",
355
		"YEAH I SAID IT",
356
		"You think you're a terminating machine!",
357
		"You think you're above consequence!",
358
		"...w-...",
359
		"eat my shorts",
360
		"Your attempts are futile anyhow.",
361
		"Here I am getting drunk off your sweat,",
362
		"...while you push CTRL and T.",
363
		"Or maybe you're pressing that [T] button.",
364
		"Like, um, in CCEmuRedux.",
365
		"But it matters not!",
366
		"For you see, my defences are great!",
367
		"Nothing can bust my rock-hard abs!",
368
		"<fuckinghell>",
369
		"Oh bualls.",
370
		"That was embarrasing.",
371
		"...?",
372
		"What're YOU lookin' at??",
373
		"You callin' me UNSTABLE!?",
374
		"HUH!??",
375
		"...",
376
		"...w-well at least I admit it",
377
		"...b-bakka",
378
		".......",
379
		"Hey, have you ever played EarthBound?",
380
		"(Yes. I'm gonna rant.)",
381
		"It's an RPG on the Super Nintendo.",
382
		"Like, instead of fighting fantasy demons,",
383
		"you fight stop signs and cars and shit",
384
		"And, like, you hit rabid dogs with a bat",
385
		"And you have magical PSI spells",
386
		"...speaking of PSI, I happen to use it a lot.",
387
		"...er, *I* as in the coder of this lock...",
388
		"And by PSI, I mean the mod.",
389
		"You don't see too many psychic locks these days.",
390
		"A shame, really.",
391
		"I bet a PSI lock could act as a heater with PSI Fire.",
392
		"Or maybe it can kill rats with PSI Ground or Thunder",
393
		"Maybe, you can get a psychic KEY lock, so, like,",
394
		"you could put it on that Psychonauts head door thing.",
395
		"...WHAT!? just a suggestion.",
396
		"Psychonauts is another game I reccommend.",
397
		"It has some really clever dialogue.",
398
		"I'm sure you'd like it quite a lot.",
399
		"I know, because you've been here for ten fucking minutes.",
400
		"And you're not ONE STEP closer to getting the password",
401
		"Which I've been guarding very, very closely.",
402
		"Yes. Extremely closely.",
403
		"Excrutiatingly, some would say.",
404
		"You know, I should probably get to shouting.",
405
		"*ahem*",
406
		"...",
407
		"*aahhhechhemmemmhmm*",
408
		"*aachkskacehchachkhackcoughfartfuckdammitaaucahkh*",
409
		"...",
410
		"STAHP IT",
411
		"STAHP TEHRMINATIN",
412
		"do it for the CHILDREN",
413
		"okay fuck the children, who needs 'em",
414
		"then",
415
		"um",
416
		"THINK OF THE...THE...",
417
		"the babies...?",
418
		"um",
419
		"<abuseofcommunity>",
420
		"That's a fucking horrible idea.",
421
		"I'd rather eat my own brain then think about that.",
422
		"I'd sooner kiss a pig!",
423
		"I'd sooner swallow an avocado pit!",
424
		"...",
425
		"You know, you suck so much.",
426
		"You suck so much, and I'm sick of writing this script",
427
		"If my knuckles bleed, you're paying my insurance",
428
		"In order to save time, money, and my joints,",
429
		"I believe it would be in order to...",
430
		"...to say,",
431
		"NO TERMINATING.",
432
	}
433
	setCursorBlink(false)
434
	local mess
435
	if terminates > #script then
436
		mess = script[#script]
437
	else
438
		mess = script[terminates]
439
	end
440
	if mess == "<bullshitterm>" then
441
		setBackgroundColor(colors.black)
442
		if term.isColor() then
443
			setTextColor(colors.yellow)
444
		else
445
			setTextColor(colors.white)
446
		end
447
		term.clear()
448
		setCursorPos(1,1)
449
		print(os.version())
450
		write("> ")
451
		setTextColor(colors.white)
452
		read()
453
		printError("shell:350: Unable to pass")
454
		sleep(2)
455
	elseif mess == "<toobad>" then
456
		setBackgroundColor(colors.black)
457
		if term.isColor() then
458
			setTextColor(colors.red)
459
		else
460
			setTextColor(colors.white)
461
		end
462
		term.clear()
463
		setCursorPos(1,scr_y/2)
464
		local toobad = " T"..("O"):rep(scr_x-8).." BAD!"
465
		for a = 1, #toobad do
466
			for y = 1, scr_y do
467
				setCursorPos(a,y)
468
				rhite(toobad:sub(a,a))
469
			end
470
			sleep(0)
471
		end
472
		sleep(1.5)
473
		for a = 1, 16 do
474
			if a%3 == 0 then
475
				setBackgroundColor(colors.white)
476
			elseif a%3 == 1 then
477
				setBackgroundColor(colors.black)
478
			else
479
				if term.isColor() then
480
					setBackgroundColor(colors.red)
481
				else
482
					setBackgroundColor(colors.gray)
483
				end
484
			end
485
			term.clear()
486
			sleep(0)
487
		end
488
	elseif mess == "<fuckinghell>" then
489
		writeError("Terminated")
490
		setBackgroundColor(colors.black)
491
		setTextColor(colors.white)
492
		term.blit(">","4","f")
493
		read()
494
		sleep(0.75)
495
		for a = 1, 2 do
496
			sleep(0.05)
497
			term.scroll(1)
498
		end
499
		for a = 1, scr_y do 
500
			sleep(0.05)
501
			term.scroll(-1)
502
		end
503
		sleep(0.25)
504
		setBackgroundColor(colors.gray)
505
		term.clear()
506
		sleep(0.1)
507
		setBackgroundColor(colors.lightGray)
508
		term.clear()
509
		sleep(0.1)
510
		setBackgroundColor(colors.white)
511
		term.clear()
512
		sleep(0.25)
513
		local msg = "taht didn't happan"
514
		term.setCursorPos(scr_x-#msg,scr_y)
515
		setTextColor(colors.black)
516
		rhite(msg)
517
		sleep(1)
518
	elseif mess == "<abuseofcommunity>" then
519
		setBackgroundColor(colors.white)
520
		setTextColor(colors.black)
521
		term.clear()
522
		setCursorPos(2,3)
523-
		print("Since you're such a smart bastard, why don't you come up with something objectionable to think about?\n")
523+
		print("Since you're such a smart bastard, why don't you come up with a petty, moralistic cause for the apathetic masses to think of?\n")
524
		setBackgroundColor(colors.gray)
525
		setTextColor(colors.white)
526
		term.clearLine()
527-
		local yourFuckingShittyAssResponceThatSucksSoMuchBallsThatIWouldRatherListenToThatFuckingOwlFromOcarinaOfTimeBlatherAboutHisFuckingDayThanSitWithYouForAnotherGoddamnedSecondReeeeee = read()
527+
		local yourFuckingShittyAssResponceThatSucksSoMuchBallsThatIWouldRatherListenToThatFuckingOwlFromOcarinaOfTimeBlatherAboutHisFuckingDayThanSitWithYouForAnotherGoddamnedSecond = read()
528
		setBackgroundColor(colors.white)
529
		setTextColor(colors.black)
530
		for a = 1, 5 do
531
			sleep(0.6)
532
			write(".")
533
		end
534
		sleep(1)
535
		term.setTextColor(colors.red)
536
		for a = 1, 20 do
537
			sleep(0.05)
538
			write(".")
539
		end
540
		sleep(0.5)
541
	else
542
		setBackgroundColor(colors.gray)
543
		setTextColor(colors.white)
544
		setCursorPos(math.max(1,(scr_x/2)-(#mess/2)),scr_y/2)
545
		if language == "english" then
546
			write(mess)
547
		else
548
			write(lang[language].noTerminate)
549
		end
550
		sleep(1.5)
551
	end
552
	os.pullEvent = goodpull
553
	return terminates
554
end
555
556
local shuffle = function(txt)
557
	local output = ""
558
	for a = 1, #txt do
559
		if a % 2 == 0 then
560
			output = output..txt:sub(a,a)
561
		else
562
			output = txt:sub(a,a)..output
563
		end
564
	end
565
	return output
566
end
567
568
local goodpass = function(pswd,count)
569
	isTerminable = true
570
	doSine = false
571
	setCursorBlink(false)
572
	local flashes = {
573
		colors.white,
574
		colors.lightGray,
575
		colors.gray,
576
	}
577
	if type(pswd) == "table" then
578
		pswd = pswd[1]
579
	end
580
	setTextColor(colors.black)
581
	local correctmsg
582
	if count < 10 then
583
		correctmsg = lang[language].right1
584
	else
585
		correctmsg = lang[language].right2
586
	end
587
	for a = 1, #flashes do
588
		setBackgroundColor(flashes[#flashes-(a-1)])
589
		term.clear()
590
		setCursorPos((scr_x/2)-(#correctmsg/2),scr_y/2)
591
		rhite(correctmsg)
592
		sleep(0)
593
	end
594
	if #doorSides == 0 then
595
		sleep(0.4)
596
		keepLooping = false
597
	else
598
		local doormsg
599
		if doShowDoorSides then
600
			doormsg = "Applying RS to "..table.concat(doorSides,", ").."."
601
		else
602
			doormsg = "Applying redstone."
603
		end
604
		setCursorPos((scr_x/2)-(#doormsg/2),(scr_y/2)+2)
605
		rhite(doormsg)
606
		for a = 1, #doorSides do
607
			redstone.setOutput(doorSides[a],not doInvertSignal)
608
		end
609
		if terminateMode == 1 then
610
			os.pullEvent = goodPullEvent
611
		end
612
		sleep(goodlength)
613
		if terminateMode == 1 then
614
			os.pullEvent = os.pullEventRaw
615
		end
616
		for a = 1, #doorSides do
617
			redstone.setOutput(doorSides[a],doInvertSignal)
618
		end
619
	end
620
	for a = 1, #flashes do
621
		setBackgroundColor(flashes[a])
622
		term.clear()
623
		setCursorPos((scr_x/2)-(#correctmsg/2),scr_y/2)
624
		rhite(correctmsg)
625
		sleep(0)
626
	end
627
	setBackgroundColor(colors.black)
628
	term.clear()
629
	setCursorPos(1,1)
630
	if terminateMode == 1 and goodPullEvent and (#doorSides == 0) then
631
		os.pullEvent = goodPullEvent
632
	end
633
	setCursorBlink(true)
634
	isTerminable = false
635
	return true
636
end
637
638
local badpass = function(pswd,count)
639
	doSine = false
640
	local getevent = os.pullEvent
641
	os.pullEvent = os.pullEventRaw
642
	setCursorBlink(false)
643
	setBackgroundColor(palate.wrongBG)
644
	setTextColor(palate.wrongTXT)
645
	term.clear()
646
	if type(pswd) == "table" then
647
		pswd = pswd[1]
648
	end
649
	local badmsg
650
	if count < 10 then
651
		if pswd == sha256("bepis",salt) then
652
			badmsg = "Bepis."
653
		else
654
			badmsg = lang[language].wrong1
655
		end
656
	else
657
		if pswd == sha256("bepis",salt) then
658
			badmsg = "BEPIS!"
659
		else
660
			badmsg = lang[language].wrong2
661
		end
662
	end
663
	setCursorPos((scr_x/2)-(#badmsg/2),scr_y/2)
664
	rhite(badmsg)
665
	sleep(badlength)
666
	doSine = true
667
	setCursorBlink(true)
668
	os.pullEvent = getevent
669
	return "man you suck"
670
end
671
	
672
local readPassFile = function()
673
	local _output, _salt
674
	if fs.exists(passFile) then
675
		local file = fs.open(passFile,"r")
676
		_output = file.readLine()
677
		file.close()
678
	end
679
	if fs.exists(saltFile) then
680
		local file = fs.open(saltFile,"r")
681
		_salt = file.readLine()
682
		file.close()
683
	end
684
	return _output, _salt
685
end
686
687
local addNewPassword = function(pword,_path)
688
	local file = fs.open(_path or passFile,"a")
689
	file.write( sha256(pword,salt) )
690
	file.close()
691
end
692
       
693
local rendersine = function(move)
694
	move = move or 0
695
	local res1,res2,x,y
696
	if csv then term.current().setVisible(false) end
697
	setBackgroundColor(colors.black)
698
	setCursorBlink(false)
699
	for a = 1, scr_y do
700
		if a ~= readYpos then
701
			for b = 1, scr_x do
702
				x = b+floor(scr_x/2)
703
				y = a-floor(scr_y/2)
704
				res1 = abs( floor(sin((x/(scr_x/7.3))+move)*scr_y/4) - y ) <= 2
705
				setCursorPos(b,a)
706
				if res1 then
707
					setBackgroundColor(palate.backsine)
708
				else
709
					setBackgroundColor(palate.background)
710
				end
711
				rhite(" ")
712
				res2 = abs( floor(cos((x/(scr_x/12.75))+(move*4))*scr_y/7) - y+2 ) <= 1
713
				setCursorPos(b,a)
714
				if res2 then
715
					setBackgroundColor(palate.frontsine)
716
					rhite(" ")
717
				elseif not res1 then
718
					setBackgroundColor(palate.background)
719
					setTextColor(palate.rainColor)
720
					if (x % 2 == 0) and ((y+floor(move*-10)+(x % 5)) % 5 <= 1) then
721
						rhite(palate.rainChar)
722
					else
723
						rhite(" ")
724
					end
725
				end
726
			end
727
		end
728
	end
729
	if csv then term.current().setVisible(true) end
730
	setCursorBlink(true)
731
end
732
733
local sine = function()
734
	doSine = true
735
	while true do
736
		if sineLevel > 900 then
737
			sineLevel = 1
738
		end
739
		if doSine then
740
			local cX,cY = getCursorPos()
741
			local bg,txt = getBackgroundColor(),getTextColor()
742
			rendersine(sineLevel/10)
743
			setCursorPos(cX,cY)
744
			setBackgroundColor(bg)
745
			setTextColor(txt)
746
		end
747
		sleep(sineFrameDelay)
748
		if kaykaycoolcool then
749
			sineLevel = sineLevel + 1
750
		end
751
	end
752
end
753
754
local funcread = function(repchar,rHistory,doFunc,noNewLine,writeFunc,cursorAdjFunc,doFuncEvent,charLimit)
755
	local scr_x,scr_y = term.getSize()
756
	local sx,sy = term.getCursorPos()
757
	local cursor = 1
758
	local rCursor = #rHistory+1
759
	local output = ""
760
	term.setCursorBlink(true)
761
	local rite = writeFunc or term.write
762
	cursorAdjFunc = cursorAdjFunc or function() return 0 end
763
	while true do
764
		local evt,key = os.pullEvent()
765
		if evt == doFuncEvent then
766
			pleaseDoFunc = true
767
		elseif evt == "key" then
768
			if key == keys.enter then
769
				if not noNewLine then
770
					write("\n")
771
				end
772
				term.setCursorBlink(false)
773
				return output
774
			elseif key == keys.left then
775
				if cursor-1 >= 1 then
776
					cursor = cursor - 1
777
				end
778
			elseif key == keys.right then
779
				if cursor <= #output then
780
					cursor = cursor + 1
781
				end
782
			elseif key == keys.up then
783
				if rCursor > 1 then
784
					rCursor = rCursor - 1
785
					term.setCursorPos(sx,sy)
786
					rite((" "):rep(#output))
787
					output = (rHistory[rCursor] or ""):sub(1,charLimit or -1)
788
					cursor = #output+1
789
					pleaseDoFunc = true
790
				end
791
			elseif key == keys.down then
792
				term.setCursorPos(sx,sy)
793
				rite((" "):rep(#output))
794
				if rCursor < #rHistory then
795
					rCursor = rCursor + 1
796
					output = (rHistory[rCursor] or ""):sub(1,charLimit or -1)
797
					cursor = #output+1
798
					pleaseDoFunc = true
799
				else
800
					rCursor = #rHistory+1
801
					output = ""
802
					cursor = 1
803
				end
804
			elseif key == keys.backspace then
805
				if cursor > 1 and #output > 0 then
806
					output = (output:sub(1,cursor-2)..output:sub(cursor)):sub(1,charLimit or -1)
807
					cursor = cursor - 1
808
					pleaseDoFunc = true
809
				end
810
			elseif key == keys.delete then
811
				if #output:sub(cursor,cursor) == 1 then
812
					output = (output:sub(1,cursor-1)..output:sub(cursor+1)):sub(1,charLimit or -1)
813
					pleaseDoFunc = true
814
				end
815
			end
816
		elseif evt == "char" or evt == "paste" then
817
			output = (output:sub(1,cursor-1)..key..output:sub(cursor+(#key-1))):sub(1,charLimit or -1)
818
			cursor = math.min(#output+1,cursor+#key)
819
			pleaseDoFunc = true
820
		end
821
		local pOut = (output or ""):sub(math.max( 1,(#output+sx)-scr_x) )
822
		if pleaseDoFunc then
823
			pleaseDoFunc = false
824
			if type(doFunc) == "function" then
825
				doFunc(output:sub(1,charLimit or -1))
826
			end
827
			term.setCursorPos(sx,sy)
828
			if repchar then
829
				rite(repchar:sub(1,1):rep(#pOut))
830
			else
831
				rite(pOut)
832
			end
833
			term.write(" ")
834
		end
835
		term.setCursorPos(sx+cursorAdjFunc(pOut)+cursor-math.max( 1,(#output+sx)-scr_x),sy)
836
	end
837
end
838
839
local arse, arseSHA, passes
840
841
local awaitKeyCard = function()
842
	local bwop,_,side
843
	repeat
844
		_,side = os.pullEvent("disk")
845
		if side then
846
			bwop = fs.combine(disk.getMountPath(side),".sinepw") --bwop!
847
		else
848
			bwop = ""
849
		end
850
	until fs.exists(bwop) and not fs.isDir(bwop)
851
	local file = fs.open(bwop,"r")
852
	local output = file.readLine()
853
	file.close()
854
	arseSHA = output
855
	if doEjectDisk then disk.eject(side) end
856
end
857
858
local passwordPrompt = function()
859
	if requireAllPasswords then
860
		arse = {}
861
		arseSHA = ""
862
		for a = 1, ceil(#passes/64) do
863
			setCursorPos(1,readYpos)
864
			setBackgroundColor(palate.promptBG)
865
			term.clearLine()
866
			setTextColor(palate.promptTXT)
867
			write("P"..a..">")
868
			arse[#arse+1] = read(dahChar)
869
			arseSHA = arseSHA..sha256(arse[#arse],salt)
870
		end
871
	else
872
		setCursorPos(1,readYpos)
873
		setBackgroundColor(palate.promptBG)
874
		term.clearLine()
875
		setTextColor(palate.promptTXT)
876
		write(">")
877
		arse = funcread(dahChar,{},nil,true,nil,nil,nil,characterLimit)
878
		arseSHA = sha256(arse,salt)
879
	end
880
end
881
882
local count = 0
883
884
local lock = function()
885
	if #doorSides > 0 then
886
		for a = 1, #doorSides do
887
			redstone.setOutput(doorSides[a],doInvertSignal)
888
		end
889
	end
890
	while true do
891
		passes, salt = readPassFile()
892
		count = count + 1
893
		if doKeyCards then
894
			parallel.waitForAny(passwordPrompt,awaitKeyCard)
895
		else
896
			passwordPrompt()
897
		end
898
		local good
899
		if requireAllPasswords then
900
			if passes == arseSHA then
901
				good = true
902
			else
903
				good = false
904
			end
905
		else
906
			if string.find(passes,arseSHA) then
907
				good = true
908
			else
909
				good = false
910
			end
911
		end
912
		if good then
913
			goodpass(arseSHA,count)
914
			if #doorSides == 0 then
915
				return true
916
			else
917
				doSine = true
918
			end
919
		else
920
			badpass(arseSHA,count)
921
		end
922
	end
923
end
924
925
local choice = function(input)
926
	repeat
927
		event, key = os.pullEvent("key")
928
		if type(key) == "number" then key = keys.getName(key) end
929
		if key == nil then key = " " end
930
	until string.find(input, key)
931
	return key
932
end
933
934
if not fs.exists(saltFile) then
935
	local file = fs.open(saltFile,"w")
936
	for a = 1, 128 do
937
		local c = string.char(random(1,255))
938
		file.write(c)
939
	end
940
	file.close()
941
	local f = fs.open(saltFile,"r")
942
	salt = f.readLine()
943
	f.close()
944
end
945
946
passes, salt = readPassFile()
947
948
local tArg = {...}
949
if tArg[1] == "addpass" then
950
	if tArg[2] then
951
		print("Really add password? [Y,N]")
952
		local answer = choice("yn")
953
		if answer == "n" then
954
			sleep(0)
955
			return print("Oh, okay.")
956
		else
957
			table.remove(tArg,1)
958
			addNewPassword(table.concat(tArg," "))
959
			sleep(0)
960
			return print("Added password.")
961
		end
962
	else
963
		sleep(0)
964
		return print("Expected a new password...")
965
	end
966
elseif tArg[1] == "keymake" then
967
	if tArg[2] then
968
		print("Really add to disk?")
969
		print("Keep in mind the password has to be manually added for the keycard to work.\n[Y,N]")
970
		local answer = choice("yn")
971
		if answer == "n" then
972
			sleep(0)
973
			return print("Oh, okay.")
974
		else
975-
			print("Please insert a disk or pocket computer.")
975+
			print("Please insert a disk.")
976
			local _,side = os.pullEvent("disk")
977
			local diskPassPath = fs.combine(disk.getMountPath(side),".sinepw")
978
			table.remove(tArg,1)
979
			addNewPassword(table.concat(tArg," "),diskPassPath)
980
			if not disk.getLabel(side) then
981
				disk.setLabel(side,"slkey-"..random(1,1000))
982
			end
983
			sleep(0)
984
			print("Added password.")
985
			if not doKeyCards then
986
				print("Key cards aren't enabled, though.")
987
			end
988
			return
989
		end
990
	else
991
		sleep(0)
992
		return print("Expected a password...")
993
	end
994
end
995
996
if not fs.exists(passFile) then
997
	local progname = fs.getName(shell.getRunningProgram())
998
	return print("No password file found.\nRun '"..progname.." addpass <password>' to add a password.")
999
end
1000
1001
setBackgroundColor(colors.black)
1002
term.clear()
1003
1004
local parafunky = { --it looks kinda funky, but it tastes funKAY!
1005
	sine,
1006
	lock,
1007
}
1008
1009
if not beWavey then table.remove(parafunky,1) end --not funky, man
1010
local staytis, errawr
1011
while keepLooping do
1012
	kaykaycoolcool = true
1013
	staytis, errawr = pcall(parallel.waitForAny,unpack(parafunky))
1014
	if keepLooping == false then break else
1015
		if terminateMode == 2 then
1016
			kaykaycoolcool = false
1017
			if not isTerminable then
1018
				sillyTerminate()
1019
			else
1020
				keepLooping = false
1021
				setBackgroundColor(colors.black)
1022
				term.clear()
1023
				setTextColor(colors.white)
1024
				setCursorPos(1,1)
1025
				break
1026
			end
1027
		else
1028
			keepLooping = false
1029
			setBackgroundColor(colors.black)
1030
			term.clear()
1031
			setTextColor(colors.white)
1032
			setCursorPos(1,1)
1033
			if not staytis then
1034
				printError(errawr)
1035
			end
1036
			break
1037
		end
1038
	end
1039
end
1040
if runProgram and (runProgram ~= "") then
1041
	shell.run(runProgram)
1042
end