AsmBB

Check-in [9cea868555]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Special processing on the cases of disabled email confirmations. Additional bot protection on registering and login forms.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9cea86855573c5beb9fdbe6e646fb302da8a922f
User & Date: johnfound 2018-11-20 20:28:26
Context
2018-11-20
20:50:20
Binary pack updated with the latest version of the bot protection. Notice, that the skins are updated as well. check-in: 943c49adf9 user: johnfound tags: trunk
20:28:26
Special processing on the cases of disabled email confirmations. Additional bot protection on registering and login forms. check-in: 9cea868555 user: johnfound tags: trunk
2018-11-17
08:06:17
Binary pack updated. check-in: ac0e89748d user: johnfound tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to source/accounts.asm.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50




51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84







85
86
87
88
89
90
91

sqlGetUserInfo   text "select id, salt, passHash, status from Users where nick = ?"
sqlInsertSession text "insert into sessions (userID, sid, FromIP, last_seen) values ( ?1, ?2, ?3, strftime('%s','now') )"
sqlUpdateSession text "update Sessions set userID = ?1, FromIP = ?3, last_seen = strftime('%s','now') where sid = ?2"
sqlCheckSession  text "select sid from sessions where userID = ? and fromIP = ?"
sqlCleanSessions text "delete from sessions where last_seen < (strftime('%s','now') - 2592000)"

sqlLoginTicket text "select ?1 as ticket"
sqlCheckLoginTicket text "select 1 from userlog where remoteIP=?1 and Client = ?2 and Param = ?3 and Activity = ?4"
sqlClearLoginTicket text "update userlog set Param = NULL where remoteIP=?1 and Activity in (1, 3, 14, 15, 16, 17)"


proc UserLogin, .pSpecial
.stmt  dd ?

.user     dd ?
.password dd ?

.userID   dd ?
.session  dd ?
.status   dd ?

.ticket   dd ?


begin
        pushad

        xor     eax, eax
        mov     [.session], eax
        mov     [.user], eax
        mov     [.password], eax
        mov     [.ticket], eax

        cinvoke sqliteExec, [hMainDatabase], sqlCleanSessions, sqlCleanSessions.length, eax, eax





; check the information

        mov     esi, [.pSpecial]
        mov     ebx, [esi+TSpecialParams.post_array]
        test    ebx, ebx
        jnz     .do_login_user

        stdcall StrCat, [esi+TSpecialParams.page_title], cLoginDialogTitle

        stdcall GetRandomString, 32
        mov     ebx, eax

        stdcall LogUserActivity, esi, uaLoggingIn, ebx

        lea     ecx, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlLoginTicket, sqlLoginTicket.length, ecx, 0

        stdcall StrPtr, ebx
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len],  SQLITE_STATIC

        cinvoke sqliteStep, [.stmt]

        stdcall RenderTemplate, 0, "form_login.tpl", [.stmt], esi
        mov     [esp+4*regEAX], eax

        cinvoke sqliteFinalize, [.stmt]
        stdcall StrDel, ebx

        clc
        popad
        return


.do_login_user:








        stdcall GetPostString, ebx, "username", 0
        mov     [.user], eax

        test    eax, eax
        jz      .redirect_back_short








|















>











>
>
>
>




















>














>
>
>
>
>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

sqlGetUserInfo   text "select id, salt, passHash, status from Users where nick = ?"
sqlInsertSession text "insert into sessions (userID, sid, FromIP, last_seen) values ( ?1, ?2, ?3, strftime('%s','now') )"
sqlUpdateSession text "update Sessions set userID = ?1, FromIP = ?3, last_seen = strftime('%s','now') where sid = ?2"
sqlCheckSession  text "select sid from sessions where userID = ? and fromIP = ?"
sqlCleanSessions text "delete from sessions where last_seen < (strftime('%s','now') - 2592000)"

sqlLoginTicket text "select ?1 as ticket, ?2 as email_flag"
sqlCheckLoginTicket text "select 1 from userlog where remoteIP=?1 and Client = ?2 and Param = ?3 and Activity = ?4"
sqlClearLoginTicket text "update userlog set Param = NULL where remoteIP=?1 and Activity in (1, 3, 14, 15, 16, 17)"


proc UserLogin, .pSpecial
.stmt  dd ?

.user     dd ?
.password dd ?

.userID   dd ?
.session  dd ?
.status   dd ?

.ticket   dd ?
.email_flag dd ?

begin
        pushad

        xor     eax, eax
        mov     [.session], eax
        mov     [.user], eax
        mov     [.password], eax
        mov     [.ticket], eax

        cinvoke sqliteExec, [hMainDatabase], sqlCleanSessions, sqlCleanSessions.length, eax, eax

        xor     eax, eax                                ; default no?
        stdcall GetParam, "email_confirm", gpInteger
        mov     [.email_flag], eax

; check the information

        mov     esi, [.pSpecial]
        mov     ebx, [esi+TSpecialParams.post_array]
        test    ebx, ebx
        jnz     .do_login_user

        stdcall StrCat, [esi+TSpecialParams.page_title], cLoginDialogTitle

        stdcall GetRandomString, 32
        mov     ebx, eax

        stdcall LogUserActivity, esi, uaLoggingIn, ebx

        lea     ecx, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlLoginTicket, sqlLoginTicket.length, ecx, 0

        stdcall StrPtr, ebx
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len],  SQLITE_STATIC
        cinvoke sqliteBindInt, [.stmt], 2, [.email_flag]
        cinvoke sqliteStep, [.stmt]

        stdcall RenderTemplate, 0, "form_login.tpl", [.stmt], esi
        mov     [esp+4*regEAX], eax

        cinvoke sqliteFinalize, [.stmt]
        stdcall StrDel, ebx

        clc
        popad
        return


.do_login_user:

        stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.x"
        jc      .redirect_back_bad_permissions

        stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.y"
        jc      .redirect_back_bad_permissions


        stdcall GetPostString, ebx, "username", 0
        mov     [.user], eax

        test    eax, eax
        jz      .redirect_back_short

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398




399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419



420
421
422
423
424
425
426
427
428
429
430
431
432
433






434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

















454
455
456
457
458


459
460
461
462
463
464
465
.user      dd ?
.password  dd ?
.password2 dd ?
.email     dd ?
.secret    dd ?
.ticket    dd ?

.email_text dd ?

begin
        pushad

        xor     eax, eax
        mov     [.user], eax
        mov     [.password], eax
        mov     [.password2], eax
        mov     [.email], eax
        mov     [.secret], eax
        mov     [.ticket], eax

; check the information





        mov     esi, [.pSpecial]
        cmp     [esi+TSpecialParams.userID], 0
        jne     .error_trick

        test    [esi+TSpecialParams.userStatus], permLogin
        jz      .error_closed_registration

        mov     ebx, [esi+TSpecialParams.post_array]
        test    ebx, ebx
        jnz     .do_register_user

        stdcall GetRandomString, 32
        mov     ebx, eax

        stdcall LogUserActivity, esi, uaRegistering, ebx

        lea     ecx, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlLoginTicket, sqlLoginTicket.length, ecx, 0

        stdcall StrPtr, ebx
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len],  SQLITE_STATIC



        cinvoke sqliteStep, [.stmt]

        stdcall RenderTemplate, 0, "form_register.tpl", [.stmt], esi
        mov     [esp+4*regEAX], eax

        cinvoke sqliteFinalize, [.stmt]
        stdcall StrDel, ebx

        clc
        popad
        return


.do_register_user:







        stdcall GetPostString, ebx, "username", 0
        mov     [.user], eax

        test    eax, eax
        jz      .error_short_name

        stdcall ValidateUserName, [.user]
        jnc     .error_short_name

        stdcall StrLen, eax
        cmp     eax, 3
        jbe     .error_short_name

        cmp     eax, 256
        ja      .error_trick

        stdcall GetPostString, ebx, "email", 0
        mov     [.email], eax


















        test    eax, eax
        jz      .error_bad_email

        stdcall CheckEmail, eax
        jc      .error_bad_email



        stdcall GetPostString, ebx, txt "password", 0
        mov     [.password], eax
        test    eax, eax
        jz      .error_short_pass

        stdcall GetPostString, ebx, txt "password2", 0







|














>
>
>
>




|
















>
>
>














>
>
>
>
>
>








|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
.user      dd ?
.password  dd ?
.password2 dd ?
.email     dd ?
.secret    dd ?
.ticket    dd ?

.email_flag dd ?

begin
        pushad

        xor     eax, eax
        mov     [.user], eax
        mov     [.password], eax
        mov     [.password2], eax
        mov     [.email], eax
        mov     [.secret], eax
        mov     [.ticket], eax

; check the information

        xor     eax, eax                                ; default no?
        stdcall GetParam, "email_confirm", gpInteger
        mov     [.email_flag], eax

        mov     esi, [.pSpecial]
        cmp     [esi+TSpecialParams.userID], 0
        jne     .error_trick

        test    [esi+TSpecialParams.userStatus], permLogin      ; For the guests, permLogin == permRegister
        jz      .error_closed_registration

        mov     ebx, [esi+TSpecialParams.post_array]
        test    ebx, ebx
        jnz     .do_register_user

        stdcall GetRandomString, 32
        mov     ebx, eax

        stdcall LogUserActivity, esi, uaRegistering, ebx

        lea     ecx, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlLoginTicket, sqlLoginTicket.length, ecx, 0

        stdcall StrPtr, ebx
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len],  SQLITE_STATIC

        cinvoke sqliteBindInt, [.stmt], 2, [.email_flag]

        cinvoke sqliteStep, [.stmt]

        stdcall RenderTemplate, 0, "form_register.tpl", [.stmt], esi
        mov     [esp+4*regEAX], eax

        cinvoke sqliteFinalize, [.stmt]
        stdcall StrDel, ebx

        clc
        popad
        return


.do_register_user:

        stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.x"
        jc      .error_trick

        stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.y"
        jc      .error_trick

        stdcall GetPostString, ebx, "username", 0
        mov     [.user], eax

        test    eax, eax
        jz      .error_short_name

        stdcall ValidateUserName, [.user]
        jnc     .error_short_name         ; the name contains special characters actually!

        stdcall StrLen, eax
        cmp     eax, 3
        jbe     .error_short_name

        cmp     eax, 256
        ja      .error_trick

        stdcall GetPostString, ebx, "email", 0
        mov     [.email], eax

        cmp     [.email_flag], 0
        jne     .check_email

; Use the email field as a honeypot, if the activation emails are disabled.
; Some kind of bot protection...

        test    eax, eax
        jz      .check_password

        stdcall StrLen, eax
        test    eax, eax
        jz      .check_password

        jmp     .error_trick

; Check the email in case the activation email will be sent
.check_email:
        test    eax, eax
        jz      .error_bad_email

        stdcall CheckEmail, eax
        jc      .error_bad_email

.check_password:

        stdcall GetPostString, ebx, txt "password", 0
        mov     [.password], eax
        test    eax, eax
        jz      .error_short_pass

        stdcall GetPostString, ebx, txt "password2", 0
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

        stdcall StrLen, eax
        test    eax, eax
        jz      .error_trick

; check the ticket

        DebugMsg "Check the tcket."

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckLoginTicket, sqlCheckLoginTicket.length, eax, 0
        cinvoke sqliteBindInt, [.stmt], 1, [esi+TSpecialParams.remoteIP]

        stdcall ValueByName, [esi+TSpecialParams.params], "HTTP_USER_AGENT"
        jc      .client_ok







|







531
532
533
534
535
536
537
538
539
540
541
542
543
544
545

        stdcall StrLen, eax
        test    eax, eax
        jz      .error_trick

; check the ticket

        DebugMsg "Check the ticket."

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckLoginTicket, sqlCheckLoginTicket.length, eax, 0
        cinvoke sqliteBindInt, [.stmt], 1, [esi+TSpecialParams.remoteIP]

        stdcall ValueByName, [esi+TSpecialParams.params], "HTTP_USER_AGENT"
        jc      .client_ok
538
539
540
541
542
543
544
545



546



547


548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568



569



570


571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
; check whether the user exists

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckUserExists, -1, eax, 0

        stdcall StrPtr, [.user]
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC




        stdcall StrPtr, [.email]



        cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC



        cinvoke sqliteStep, [.stmt]
        mov     ebx, eax

        cinvoke sqliteFinalize, [.stmt]

        cmp     ebx, SQLITE_ROW
        je      .error_exists

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlRegisterUser, sqlRegisterUser.length, eax, 0

        stdcall StrPtr, [.user]
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC

        stdcall StrPtr, [.password]
        cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC

        stdcall StrPtr, [.password2]
        cinvoke sqliteBindText, [.stmt], 3, eax, [eax+string.len], SQLITE_STATIC




        stdcall StrPtr, [.email]



        cinvoke sqliteBindText, [.stmt], 4, eax, [eax+string.len], SQLITE_STATIC



        cinvoke sqliteBindInt, [.stmt], 5, [esi+TSpecialParams.remoteIP]

        stdcall StrPtr, [.secret]
        cinvoke sqliteBindText, [.stmt], 6, eax, [eax+string.len], SQLITE_STATIC

        cinvoke sqliteBindInt, [.stmt], 7, uopCreateAccount

        cinvoke sqliteStep, [.stmt]
        mov     ebx, eax

        cinvoke sqliteFinalize, [.stmt]

        cmp     ebx, SQLITE_DONE
        jne     .error_exists

        stdcall GetParam, "email_confirm", gpInteger
        jc      .send_emails

        test    eax, eax
        jz      .no_confirm

; now send the activation email for all registered user, where the email was not sent.

.send_emails:
        stdcall ProcessActivationEmails

; the user has been created and now is waiting for email activation.

        stdcall TextMakeRedirect, 0, "/!message/user_created/"
        jmp     .finish









>
>
>

>
>
>

>
>





















>
>
>

>
>
>

>
>
















<
<
|
<
|



<







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647


648

649
650
651
652

653
654
655
656
657
658
659
; check whether the user exists

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckUserExists, -1, eax, 0

        stdcall StrPtr, [.user]
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC

        cmp     [.email], 0
        je      .email_ok2

        stdcall StrPtr, [.email]
        cmp     [eax+string.len], 0
        je      .email_ok2

        cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC

.email_ok2:

        cinvoke sqliteStep, [.stmt]
        mov     ebx, eax

        cinvoke sqliteFinalize, [.stmt]

        cmp     ebx, SQLITE_ROW
        je      .error_exists

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlRegisterUser, sqlRegisterUser.length, eax, 0

        stdcall StrPtr, [.user]
        cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC

        stdcall StrPtr, [.password]
        cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC

        stdcall StrPtr, [.password2]
        cinvoke sqliteBindText, [.stmt], 3, eax, [eax+string.len], SQLITE_STATIC

        cmp     [.email], 0
        je      .email_ok

        stdcall StrPtr, [.email]
        cmp     [eax+string.len], 0
        je      .email_ok

        cinvoke sqliteBindText, [.stmt], 4, eax, [eax+string.len], SQLITE_STATIC

.email_ok:

        cinvoke sqliteBindInt, [.stmt], 5, [esi+TSpecialParams.remoteIP]

        stdcall StrPtr, [.secret]
        cinvoke sqliteBindText, [.stmt], 6, eax, [eax+string.len], SQLITE_STATIC

        cinvoke sqliteBindInt, [.stmt], 7, uopCreateAccount

        cinvoke sqliteStep, [.stmt]
        mov     ebx, eax

        cinvoke sqliteFinalize, [.stmt]

        cmp     ebx, SQLITE_DONE
        jne     .error_exists



        cmp     [.email_flag], 0

        je      .no_confirm

; now send the activation email for all registered user, where the email was not sent.


        stdcall ProcessActivationEmails

; the user has been created and now is waiting for email activation.

        stdcall TextMakeRedirect, 0, "/!message/user_created/"
        jmp     .finish

Changes to source/commands.asm.

1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308



gpString  = 0
gpInteger = 1


sqlGetParam      text "select val from params where id = ?"

proc GetParam, .key, .type
.stmt dd ?
begin
        pushad

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlGetParam, -1, eax, 0

        stdcall StrPtr, [.key]
        cinvoke sqliteBindText, [.stmt], 1, eax, -1, SQLITE_STATIC

        cinvoke sqliteStep, [.stmt]
        cmp     eax, SQLITE_ROW
        jne     .error







|







|







1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308



gpString  = 0
gpInteger = 1


sqlGetParam text "select val from params where id = ?"

proc GetParam, .key, .type
.stmt dd ?
begin
        pushad

        lea     eax, [.stmt]
        cinvoke sqlitePrepare_v2, [hMainDatabase], sqlGetParam, sqlGetParam.length, eax, 0

        stdcall StrPtr, [.key]
        cinvoke sqliteBindText, [.stmt], 1, eax, -1, SQLITE_STATIC

        cinvoke sqliteStep, [.stmt]
        cmp     eax, SQLITE_ROW
        jne     .error

Changes to source/engine.asm.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
options.ShowSizes = 0

options.DebugMode = 0
options.AlignCode = 0
options.ShowImported = 0

options.DebugWeb = 0
options.DebugPost = 1           ; save the latest POST request data in the file "post_data.txt"
options.DebugSQLite = 1

options.DebugWebSSE = 0         ; debug server sent events - creates a command "!echo_events" for debugging SSE.
options.Benchmark = 0

;HeapManager  equ ASM
;LinuxThreads equ native







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
options.ShowSizes = 0

options.DebugMode = 0
options.AlignCode = 0
options.ShowImported = 0

options.DebugWeb = 0
options.DebugPost = 0           ; save the latest POST request data in the file "post_data.txt"
options.DebugSQLite = 1

options.DebugWebSSE = 0         ; debug server sent events - creates a command "!echo_events" for debugging SSE.
options.Benchmark = 0

;HeapManager  equ ASM
;LinuxThreads equ native

Changes to www/templates/Terminal/form_login.tpl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[css:navigation.css]
[css:login.css]

  <div class="ui_panel">
    <a class="ui left" href="/">Threads</a>
  </div>
  <form class="login-block" method="post" target="_self" action="/!login">
    <h1>Login</h1>
    <input type="text" value="" placeholder="Username" name="username" class="username" autofocus maxlength="256">
    <input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off">
    <input type="hidden" value="[special:referer]" name="backlink" id="backlink">
    <input type="checkbox" name="persistent" id="pr" value="1"><label for="pr">Persistent login</label>
    <input type="hidden" value="[ticket]" name="ticket" id="ticket">
    <input type="submit" name="submit" class="ui left" value="Submit">
  </form>
  <article>
    <p>If you forgot your password, <b><a href="/!resetpassword">click here</a></b>. You have limited reset attempts.</p>
    [case:[special:canregister]||<p>If you don't have an account, you should <b><a href="/!register">register one</a></b>.</p>]
    <p></p>
    <p>The login process uses cookies. If the "Persistent login" checkbox is checked, the cookie will be stored persistently in your browser.</p>
    <p>If the "Persistent login" checkbox is not checked (default), AsmBB uses so called "session cookies" that are automatically removed when you close your browser.</p>
    <p>When you logout from the forum, all cookies are removed as well.</p>
  </article>








|
|
|
|
|
|


|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[css:navigation.css]
[css:login.css]

  <div class="ui_panel">
    <a class="ui left" href="/">Threads</a>
  </div>
  <form class="login-block" method="post" target="_self" action="/!login">
    <h1>Login</h1>
    <p class="pi_nick"><input type="text" value="" placeholder="Username" name="username" class="username" autofocus maxlength="256"></p>
    <p class="pi_pass"><input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off"></p>
    <p class="pi_tick"><input type="text" value="[special:referer]" name="backlink" id="backlink"></p>
    <p class="pi_nick"><input type="checkbox" name="persistent" id="pr" value="1"><label for="pr">Persistent login</label></p>
    <p class="pi_tick"><input type="text" value="[ticket]" name="ticket" id="ticket"></p>
    <input type="image" name="submit" id="submit" value="Submit"><label class="submit" for="submit">Submit</label>
  </form>
  <article>
    [case:[email_flag]||<p>If you forgot your password, <b><a href="/!resetpassword">click here</a></b>. You have limited reset attempts.</p>]
    [case:[special:canregister]||<p>If you don't have an account, you should <b><a href="/!register">register one</a></b>.</p>]
    <p></p>
    <p>The login process uses cookies. If the "Persistent login" checkbox is checked, the cookie will be stored persistently in your browser.</p>
    <p>If the "Persistent login" checkbox is not checked (default), AsmBB uses so called "session cookies" that are automatically removed when you close your browser.</p>
    <p>When you logout from the forum, all cookies are removed as well.</p>
  </article>

Changes to www/templates/Terminal/login.less.

38
39
40
41
42
43
44
























input[type=checkbox] + label {
    display: block;
    color: @clFormFG;
    margin: 0 0 @LineH 0;
}





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66


input[type=checkbox] + label {
    display: block;
    color: @clFormFG;
    margin: 0 0 @LineH 0;
}

.pi_nick, .pi_pass, .pi_tick, .pi_email {
  margin: 0px;
  padding: 0px;
}

.pi_tick, .pi_email {
  display: none;
}

#submit {
  position: absolute;
  z-index: -1;
  left: -10000px;

  &:focus + label {
    background: @clButtonActiveBG;
    color: @clButtonActiveFG;
    outline: 2px dotted @clSeparator;
    outline-offset: -2px;
  }
}

Changes to www/templates/Wasp/form_login.tpl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[css:navigation.css]
[css:login.css]

<div class="login">
  <div class="ui">
    <a class="ui" href="/">Threads</a>
  </div>
  <form class="login-block" method="post" target="_self" action="/!login">
    <h1>Login</h1>
    <input type="text" value="" placeholder="Username" name="username" class="username" autofocus maxlength="256">
    <input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off">
    <input type="hidden" value="[special:referer]" name="backlink" id="backlink">
    <input type="checkbox" name="persistent" id="pr" value="1"><label for="pr">Persistent login</label>
    <input type="hidden" value="[ticket]" name="ticket" id="ticket">
    <input type="submit" name="submit" class="submit" value="Submit">
  </form>
  <article>
    <p>If you forgot your password, <b><a href="/!resetpassword">click here</a></b>. You have limited reset attempts.</p>
    [case:[special:canregister]||<p>If you don't have an account, you should <b><a href="/!register">register one</a></b>.</p>]
    <p></p>
    <p>The login process uses cookies. If the "Persistent login" checkbox is checked, the cookie will be stored persistently in your browser.</p>
    <p>If the "Persistent login" checkbox is not checked (default), AsmBB uses so called "session cookies" that are automatically removed when you close your browser.</p>
    <p>When you logout from the forum, all cookies are removed as well.</p>
  </article>
</div>









|
|
|
|
|
|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[css:navigation.css]
[css:login.css]

<div class="login">
  <div class="ui">
    <a class="ui" href="/">Threads</a>
  </div>
  <form class="login-block" method="post" target="_self" action="/!login">
    <h1>Login</h1>
    <p class="pi_nick"><input type="text" value="" placeholder="Username" name="username" class="username" autofocus maxlength="256"></p>
    <p class="pi_pass"><input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off"></p>
    <p class="pi_tick"><input type="text" value="[special:referer]" name="backlink" id="backlink"></p>
    <p class="pi_nick"><input type="checkbox" name="persistent" id="pr" value="1"><label for="pr">Persistent login</label></p>
    <p class="pi_tick"><input type="text" value="[ticket]" name="ticket" id="ticket"></p>
    <input type="image" name="submit" id="submit" value="Submit"><label class="submit" for="submit">Submit</label>
  </form>
  <article>
    [case:[email_flag]||<p>If you forgot your password, <b><a href="/!resetpassword">click here</a></b>. You have limited reset attempts.</p>]
    [case:[special:canregister]||<p>If you don't have an account, you should <b><a href="/!register">register one</a></b>.</p>]
    <p></p>
    <p>The login process uses cookies. If the "Persistent login" checkbox is checked, the cookie will be stored persistently in your browser.</p>
    <p>If the "Persistent login" checkbox is not checked (default), AsmBB uses so called "session cookies" that are automatically removed when you close your browser.</p>
    <p>When you logout from the forum, all cookies are removed as well.</p>
  </article>
</div>

Changes to www/templates/Wasp/form_register.tpl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[css:navigation.css]
[css:login.css]

<div class="login">
  <div class="ui">
    <a class="ui" href="/">Threads</a>
  </div>
  <form class="register-block" method="post" action="/!register/">
    <h1>Register</h1>
    <input type="text" value="" placeholder="Username" name="username" class="username" maxlength="256" autofocus>
    <input type="text" value="" placeholder="e-mail" name="email" class="email" maxlength="320">
    <input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off">
    <input type="password" value="" placeholder="Password again" name="password2" class="password" maxlength="1024" autocomplete="off">
    <input type="hidden" value="[ticket]" name="ticket" id="ticket">
    <input type="submit" name="submit" class="submit" value="Submit">
  </form>
  <article>
    <p>To choose strong password and write it down on a paper is better than to choose easy to remember password.</p>
    <p>Because the humans are not very good in remembering random strings, but pretty good in keeping small sheets of paper.</p>
    <p>But don't stick it on your monitor. Simply keep it in your wallet...</p>
    <p>... or use some password manager program.</p>
  </article>









|
|
|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[css:navigation.css]
[css:login.css]

<div class="login">
  <div class="ui">
    <a class="ui" href="/">Threads</a>
  </div>
  <form class="register-block" method="post" action="/!register/">
    <h1>Register</h1>
    <p class="pi_nick"><input type="text" value="" placeholder="Username" name="username" class="username" maxlength="256" autofocus></p>
    <p class="[case:[email_flag]|pi_email|pi_nick]"><input type="text" value="" placeholder="e-mail" name="email" class="email" maxlength="320"></p>
    <p class="pi_pass"><input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off"></p>
    <p class="pi_pass"><input type="password" value="" placeholder="Password again" name="password2" class="password" maxlength="1024" autocomplete="off"></p>
    <p class="pi_tick"><input type="text" value="[ticket]" name="ticket" id="ticket" class="ticket"></p>
    <label class="submit" for="submit">Submit</label><input type="image" name="submit" id="submit" value="Submit">
  </form>
  <article>
    <p>To choose strong password and write it down on a paper is better than to choose easy to remember password.</p>
    <p>Because the humans are not very good in remembering random strings, but pretty good in keeping small sheets of paper.</p>
    <p>But don't stick it on your monitor. Simply keep it in your wallet...</p>
    <p>... or use some password manager program.</p>
  </article>

Changes to www/templates/Wasp/login.less.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105






106
107
108
109
110
111
112









    border: @borderEdit;

    background: @bgEditor;
    color: @clEditorFG;
}



input.username {
    background-image: url('[special:skin]/_images/user.png') !important;
}

input.email {
    background-image: url('[special:skin]/_images/email.png') !important;
}

input.password {
    background-image: url('[special:skin]/_images/pass.png') !important;
}

input.username:focus, input.email:focus, input.password:focus {
    background: @bgEditorFocus;
}


input.submit {
  height: 38px;

  width: 100%;
  background: @clButtonBG;
  color: @clButtonFG;
  border: none;
  font-weight: bold;
  font-size: 16px;
  font-variant: small-caps;
  outline: none;
  cursor: pointer;
  text-align: center;
  padding: 0px;
  display: block;
  margin: 8px 0px;

  &:hover {
    background: @clButtonActiveBG;
    color: @clButtonActiveFG;
  }







  &:focus {
    background: @clButtonActiveBG;
    color: @clButtonActiveFG;
    outline: 2px dotted @clSeparator;
    outline-offset: -2px;
  }
}
















<
















>
|

>


















|
>
>
>
>
>
>
|






>
>
>
>
>
>
>
>
>
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    border: @borderEdit;

    background: @bgEditor;
    color: @clEditorFG;
}



input.username {
    background-image: url('[special:skin]/_images/user.png') !important;
}

input.email {
    background-image: url('[special:skin]/_images/email.png') !important;
}

input.password {
    background-image: url('[special:skin]/_images/pass.png') !important;
}

input.username:focus, input.email:focus, input.password:focus {
    background: @bgEditorFocus;
}


label.submit {
  height: 38px;
  line-height: 38px;
  width: 100%;
  background: @clButtonBG;
  color: @clButtonFG;
  border: none;
  font-weight: bold;
  font-size: 16px;
  font-variant: small-caps;
  outline: none;
  cursor: pointer;
  text-align: center;
  padding: 0px;
  display: block;
  margin: 8px 0px;

  &:hover {
    background: @clButtonActiveBG;
    color: @clButtonActiveFG;
  }
}

#submit {
  position: absolute;
  z-index: -1;
  left: -10000px;

  &:focus + label {
    background: @clButtonActiveBG;
    color: @clButtonActiveFG;
    outline: 2px dotted @clSeparator;
    outline-offset: -2px;
  }
}

.pi_nick, .pi_pass, .pi_tick, .pi_email {
  margin: 0px;
  padding: 0px;
}

.pi_tick, .pi_email {
  display: none;
}