include "%lib%/freshlib.inc"

@BinaryType console

options.ShowSkipped = 0
options.ShowSizes = 1
options.DebugMode = 0
options.AlignCode = 0

HeapManager  equ ASM


include "%lib%/freshlib.asm"

include 'save_response.asm'
include 'get.asm'
include 'post.asm'
include 'cgi.asm'

iglobal
  pHTMLTemplate dd cDefaultTemplate
endg


uglobal
  StartTime     dd ?

  hDocumentDir  dd ?

  hSource       dd ?

  hFileTitle    dd ?

  hSysMessage   dd ?

  hHoneypot     dd ?
  hFeedbackUser dd ?
  hFeedbackEmail dd ?

  hRemoteAddr   dd ?
  dwRemoteAddr  dd ?

  pBanList      dd ?
  dwBanListLen  dd ?

  fBanned       dd ?
endg

cSubject text "subject="
cFeedbackUser text "name="
cFeedbackEmail text "email="

cRemoteAddr text "REMOTE_ADDR"
cBanFilename text "banlist.inc"

;        rb 256          ; FASM ELF generator sometimes is buggy. Inserting some more bytes, fixes the problem.

start:
        stdcall GetTimestamp
        mov     [StartTime], eax

        InitializeAll

        stdcall InitScriptVariables
        stdcall GetPostData
        jc      .no_post_data

        stdcall GetQueryItem, [pPostContent], cSubject, 0
        mov     [hHoneypot], eax

        stdcall GetQueryItem, [pPostContent], cFeedbackUser, cDefaultNULL
        push    eax
        stdcall StrEncodeHTML, eax
        stdcall StrDel; from the stack
        mov     [hFeedbackUser], eax

        stdcall GetQueryItem, [pPostContent], cFeedbackEmail, cDefaultNULL
        mov     [hFeedbackEmail], eax

        stdcall StrClipSpacesR, eax
        stdcall StrClipSpacesL, eax

; it is work around. The function StrLCase does not work properly here.
        stdcall StrPtr, eax
        mov     ecx, [eax+string.len]
        jecxz   .email_ok
.lcase:
        cmp     byte [eax], 'A'
        jb      .next
        cmp     byte [eax], 'Z'
        ja      .next

        or      byte [eax], $40

.next:
        inc     eax
        loop    .lcase

.email_ok:
        stdcall StrClipSpacesR, [hSource]
        stdcall StrLen, [hSource]
        test    eax, eax
        jz      .finish

        stdcall StrClipSpacesR, [hFeedbackUser]
        stdcall StrClipSpacesL, [hFeedbackUser]
        stdcall StrLen, [hFeedbackUser]
        test    eax, eax
        jz      .finish

        stdcall GetEnvVariable, cRemoteAddr
        jc      .finish
        mov     [hRemoteAddr], eax

        stdcall StrIP2Num, eax
        jc      .finish

        mov     [dwRemoteAddr], eax

; check the ban list.

        stdcall StrDup, [hPath]
        stdcall StrCat, eax, cBanFilename
        push    eax

        stdcall LoadBinaryFile, eax
        stdcall StrDel; from the stack
        test    ecx, ecx
        jnz     .check_banlist

        stdcall GetMem, 16
        mov     [pBanList], eax
        mov     [dwBanListLen], ecx
        jmp     .not_banned

.check_banlist:
        mov     [pBanList], eax
        mov     edi, eax
        mov     eax, [dwRemoteAddr]
        shr     ecx, 2
        mov     [dwBanListLen], ecx

        jecxz   .not_banned
        repne scasd
        je    .finish            ; this address is banned.

.not_banned:
; check the honeypot
        cmp     [hHoneypot], 0
        je      .save_it
        stdcall StrLen, [hHoneypot]
        test    eax, eax
        jnz     .ban_it

        mov     [fBanned], FALSE

; save the feedback

.save_it:
; create the filename
        stdcall StrDup, [hPath]
        stdcall StrCat, eax, [hPageName]
        stdcall StrCharCat, eax, '.inc'
        mov     ebx, eax

.save_it_here:
; open the feedback file
        stdcall LoadBinaryFile, ebx
        mov     esi, eax
        mov     edx, ecx

        stdcall FileCreate, ebx
        jc      .file_create_error
        mov     edi, eax

                                                        cAvatarImg text '<img class="avatar" alt=":)" src="http://gravatar.com/avatar/'
                                                        cAvatarImgEnd text '?d=monsterid&amp;s=60" />'

        stdcall FileWriteString, edi, cAvatarImg

        stdcall StrMD5, [hFeedbackEmail]
        push    eax
        stdcall FileWriteString, edi, eax
        stdcall FileWriteString, edi, cAvatarImgEnd
        stdcall StrDel ; from the stack.

        stdcall FileWriteString, edi, [hFeedbackUser]
        stdcall FileWriteString, edi, cCRLF
        stdcall FileWriteString, edi, cFeedbackCommentEmail
        stdcall FileWriteString, edi, [hFeedbackEmail]
        stdcall FileWriteString, edi, cCRLF
        stdcall FileWriteString, edi, cFeedbackCommentIP
        stdcall FileWriteString, edi, [hRemoteAddr]
        stdcall FileWriteString, edi, cCRLF
        stdcall FileWriteString, edi, [hSource]
        stdcall FileWriteString, edi, cCRLF
        stdcall FileWriteString, edi, cFeedbackSeparator

cFeedbackCommentEmail   text ';;;; User e-mail: '
cFeedbackCommentIP      text ';;;; User IP: '
cFeedbackSeparator text $03, $0d, $0a

        test    edx, edx
        jz      .old_ok
        stdcall FileWrite, edi, esi, edx
.old_ok:

        stdcall FileClose, edi

        cmp     [fBanned], FALSE
        jne     .log_banned

cCommentEvent text 'comment added.'
        stdcall LogEvent, cCommentEvent, [hPageName], [hFileTitle]

cCommentSuccess text 'Comment was added.'
        stdcall StrDup, cCommentSuccess
        mov     [hSysMessage], eax
        jmp     .finish

.log_banned:

cBannedEvent text 'bot banned from commenting.'
        stdcall LogEvent, cBannedEvent, [hPageName], [hFileTitle]

cBannedSuccess text 'Comment was not added.'
        stdcall StrDup, cBannedSuccess
        mov     [hSysMessage], eax

.finish:
        stdcall ReadTemplate, cTemplateFileName
        jc      .template_ok
        mov     [pHTMLTemplate], eax

.template_ok:
        stdcall FileWrite, [STDOUT], cContentType, cContentType.length
        stdcall WriteTemplate, [pHTMLTemplate], [STDOUT], SaveVarCallback

        push    eax
        FinalizeAll
        stdcall Terminate

;..............................................................................


.no_post_data:
        stdcall StrDup, cErrorNoPost
        mov     [hSysMessage], eax
        jmp     .finish


.file_write_error:
        push    eax
        stdcall FileClose, ebx
        pop     eax

.error_read:
.file_create_error:
        stdcall StrDup, 'Error file read/write.'
        mov     [hSysMessage], eax
        jmp     .finish

.ban_it:
        mov     ecx, [dwBanListLen]
        mov     esi, [pBanList]
        mov     eax, [dwRemoteAddr]
        mov     [esi+4*ecx], eax
        inc     ecx

        shl     ecx, 2

        stdcall StrDup, [hPath]
        stdcall StrCat, eax, cBanFilename
        push    eax
        stdcall SaveBinaryFile, eax, esi, ecx
        stdcall StrDel; from the stack

        stdcall StrDup, [hPath]
        stdcall StrCat, eax, cBanedFeedbacks
        mov     ebx, eax
        mov     [fBanned], TRUE
        jmp     .save_it_here

cBanedFeedbacks  text 'BanedFeedbackPosts.inc'

cCRLF             text $0d, $0a
cTemplateFileName text 'feedback.inc'
cDefaultTemplate  text '<html><head></head><body></body></html>'


cContentType text 'Content-type: text/html', 13, 10, 13, 10


cErrorNoPost text 'Error! feedback.cgi needs post data.'




