forked from KolibriOS/kolibrios
3e023d2d81
git-svn-id: svn://kolibrios.org@6027 a494cfbc-eb01-0410-851d-a64ba20cac60
645 lines
15 KiB
PHP
645 lines
15 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
;; ;;
|
|
;; Written by hidnplayr@kolibrios.org ;;
|
|
;; ;;
|
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
|
;; Version 2, June 1991 ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
user_parser:
|
|
|
|
mov ebp, [window_active] ; print to the current window
|
|
mov [window_print], ebp
|
|
|
|
mov ecx, [edit1.size]
|
|
test ecx, ecx
|
|
jz .ret ; ignore empty commands
|
|
|
|
mov esi, input_text
|
|
mov edi, user_command
|
|
call recode ; Convert to UTF-8
|
|
mov word[edi], 0x0a0d ; terminate the line
|
|
sub edi, user_command
|
|
mov [user_command.size], edi
|
|
|
|
cmp byte[user_command], '/' ; is it a server command ?
|
|
je .command
|
|
|
|
cmp [status], STATUS_LOGGED_IN
|
|
jne .not_loggedin
|
|
|
|
cmp [ebp + window.type], WINDOWTYPE_CHANNEL
|
|
je .send_privmsg
|
|
cmp [ebp + window.type], WINDOWTYPE_CHAT
|
|
jne .not_channel
|
|
|
|
.send_privmsg:
|
|
if TIMESTAMP
|
|
call print_timestamp
|
|
end if
|
|
|
|
mov al, '<'
|
|
call print_char
|
|
|
|
mov esi, user_nick
|
|
call print_asciiz
|
|
|
|
mov al, '>'
|
|
call print_char
|
|
mov al, ' '
|
|
call print_char
|
|
|
|
mov eax, [user_command.size]
|
|
mov byte[user_command + eax],0
|
|
mov esi, user_command
|
|
call print_asciiz
|
|
|
|
mov al, 10
|
|
call print_char
|
|
|
|
; and now send it to the server
|
|
mov dword[packetbuf], 'PRIV'
|
|
mov dword[packetbuf+4], 'MSG '
|
|
|
|
lea esi, [ebp + window.name]
|
|
mov edi, packetbuf+8
|
|
mov ecx, MAX_WINDOWNAME_LEN
|
|
.loop:
|
|
lodsb
|
|
test al, al
|
|
jz .done
|
|
stosb
|
|
dec ecx
|
|
jnz .loop
|
|
.done:
|
|
|
|
mov ax, ' :'
|
|
stosw
|
|
|
|
mov esi, user_command
|
|
mov ecx, [user_command.size]
|
|
; inc ecx
|
|
rep movsb
|
|
|
|
; end the command with a CRLF
|
|
mov ax, 0x0a0d
|
|
stosw
|
|
|
|
lea esi, [edi - packetbuf]
|
|
mcall send, [socketnum], packetbuf, , 0
|
|
|
|
.ret:
|
|
ret
|
|
|
|
; Text begins with a '/' lets try to find the command in the lookup table.
|
|
.command:
|
|
mov eax, dword[user_command+1] ; skip '/'
|
|
or eax, 0x20202020 ; convert to lowercase
|
|
|
|
mov edi, user_commands
|
|
mov ecx, user_commands.number
|
|
cmp [status], STATUS_CONNECTED
|
|
jae .cmd_loop
|
|
mov ecx, user_commands.number2
|
|
.cmd_loop:
|
|
scasd
|
|
je .got_cmd
|
|
add edi, 4
|
|
dec ecx
|
|
jnz .cmd_loop
|
|
|
|
cmp [status], STATUS_CONNECTED
|
|
jb .not_connected
|
|
|
|
; Commands shorter then 3 chars are placed here
|
|
and eax, 0x00ffffff
|
|
cmp eax, 'me '
|
|
je cmd_usr_me
|
|
|
|
; If none of the listed commands, send text straight to server
|
|
jmp cmd_usr_send
|
|
|
|
.got_cmd:
|
|
jmp dword[edi]
|
|
|
|
.not_loggedin:
|
|
mov esi, str_notloggedin
|
|
call print_asciiz
|
|
ret
|
|
|
|
.not_connected:
|
|
mov esi, str_notconnected
|
|
call print_asciiz
|
|
ret
|
|
|
|
.not_channel:
|
|
mov esi, str_notchannel
|
|
call print_asciiz
|
|
ret
|
|
|
|
|
|
; user commands lookup table
|
|
user_commands:
|
|
dd 'nick', cmd_usr_nick
|
|
dd 'real', cmd_usr_real
|
|
dd 'serv', cmd_usr_server
|
|
dd 'help', cmd_usr_help
|
|
dd 'code', cmd_usr_code
|
|
|
|
.number2 = ($ - user_commands) / 8
|
|
|
|
; All following commands require a connection to the server.
|
|
dd 'quer', cmd_usr_quer
|
|
dd 'quit', cmd_usr_quit
|
|
dd 'part', cmd_usr_part
|
|
dd 'ctcp', cmd_usr_ctcp
|
|
dd 'msg ', cmd_usr_msg
|
|
|
|
.number = ($ - user_commands) / 8
|
|
|
|
|
|
|
|
cmd_usr_msg:
|
|
|
|
lea esi, [user_command+5]
|
|
|
|
mov dword[packetbuf], 'PRIV'
|
|
mov dword[packetbuf+4], 'MSG '
|
|
lea edi, [packetbuf+8]
|
|
|
|
@@:
|
|
lodsb
|
|
test al, al
|
|
jz .fail
|
|
cmp al, 10
|
|
je .fail
|
|
cmp al, 13
|
|
je .fail
|
|
stosb
|
|
cmp al, ' '
|
|
jne @r
|
|
|
|
mov al, ':'
|
|
stosb
|
|
|
|
push edi
|
|
@@:
|
|
lodsb
|
|
test al, al
|
|
jz @f
|
|
cmp al, 10
|
|
je @f
|
|
cmp al, 13
|
|
je @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
; end the command with a CRLF
|
|
mov ax, 0x0a0d
|
|
stosw
|
|
mov byte[edi], 0
|
|
|
|
lea esi, [edi - packetbuf]
|
|
mcall send, [socketnum], packetbuf, , 0
|
|
|
|
; now print to the window
|
|
if TIMESTAMP
|
|
call print_timestamp
|
|
end if
|
|
|
|
mov esi, msg_header
|
|
call print_asciiz
|
|
|
|
mov esi, packetbuf+8
|
|
mov bl, ' '
|
|
call print_string
|
|
|
|
mov al, '*'
|
|
call print_char
|
|
|
|
mov al, ' '
|
|
call print_char
|
|
|
|
pop esi
|
|
call print_asciiz
|
|
|
|
.fail:
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_quit:
|
|
|
|
mov esi, quit_msg
|
|
cmp byte[user_command+5], ' '
|
|
jne quit_server
|
|
lea esi, [user_command+6]
|
|
|
|
; esi = quit message
|
|
quit_server:
|
|
|
|
; User wants to close a channel, send PART command to server
|
|
mov dword[packetbuf], 'QUIT'
|
|
mov word[packetbuf+4], ' :'
|
|
lea edi, [packetbuf+6]
|
|
; Append our quit msg
|
|
@@:
|
|
lodsb
|
|
cmp al, 13
|
|
je @f
|
|
test al, al
|
|
jz @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
; end the command with a CRLF
|
|
mov ax, 0x0a0d
|
|
stosw
|
|
|
|
lea esi, [edi - packetbuf] ; calculate length
|
|
mcall send, [socketnum], packetbuf, , 0 ; and finally send to server
|
|
|
|
mov ebp, windows
|
|
.window_loop:
|
|
cmp [ebp + window.type], WINDOWTYPE_NONE
|
|
je .next_window
|
|
mov [window_print], ebp
|
|
if TIMESTAMP
|
|
call print_timestamp
|
|
end if
|
|
mov esi, str_disconnected
|
|
call print_asciiz
|
|
cmp [ebp + window.type], WINDOWTYPE_CHANNEL
|
|
jne .next_window
|
|
call user_remove_all
|
|
.next_window:
|
|
add ebp, sizeof.window
|
|
cmp ebp, windows + (MAX_WINDOWS * sizeof.window)
|
|
jb .window_loop
|
|
|
|
mov [status], STATUS_DISCONNECTED
|
|
mcall close, [socketnum]
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
cmd_usr_nick:
|
|
|
|
cmp [user_command.size], 5
|
|
je .justprint
|
|
cmp byte[user_command+5], ' '
|
|
jne .fail
|
|
cmp [socketnum], 0
|
|
je .dontsend
|
|
|
|
; Request nickname change to server
|
|
mov dword[user_command+1], 'NICK'
|
|
mov esi, [user_command.size]
|
|
mov word[user_command + esi], 0x0a0d
|
|
inc esi
|
|
mcall send, [socketnum], user_command+1, , 0
|
|
|
|
.fail:
|
|
ret
|
|
|
|
; We arent logged in yet, directly change user_nick field and print notification to user.
|
|
.dontsend:
|
|
mov ecx, MAX_NICK_LEN
|
|
mov esi, user_command+6
|
|
mov edi, user_nick
|
|
@@:
|
|
lodsb
|
|
cmp al, 13
|
|
je @f
|
|
stosb
|
|
dec ecx
|
|
jnz @r
|
|
@@:
|
|
xor al, al
|
|
stosb
|
|
|
|
.justprint:
|
|
mov esi, str_nickchange
|
|
call print_asciiz
|
|
|
|
mov esi, user_nick
|
|
call print_asciiz
|
|
|
|
mov al, 10
|
|
call print_char
|
|
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_real:
|
|
|
|
cmp byte[user_command+5], ' '
|
|
jne cmd_usr_send
|
|
|
|
mov ecx, MAX_REAL_LEN
|
|
mov esi, user_command+6
|
|
mov edi, user_real_name
|
|
.loop:
|
|
lodsb
|
|
cmp al, 13
|
|
je .done
|
|
stosb
|
|
dec ecx
|
|
jnz .loop
|
|
.done:
|
|
xor al, al
|
|
stosb
|
|
|
|
mov esi, str_realchange
|
|
call print_asciiz
|
|
|
|
mov esi, user_real_name
|
|
call print_asciiz
|
|
|
|
mov al, 10
|
|
call print_char
|
|
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_server:
|
|
|
|
mov eax, dword[user_command+5] ; check for 'er ', we only checked 'serv'
|
|
or eax, 0x00002020
|
|
and eax, 0x00ffffff
|
|
cmp eax, 'er '
|
|
jne cmd_usr_send
|
|
|
|
; Server window is always first window in the list, switch to it.
|
|
mov [window_print], windows
|
|
mov [window_active], windows
|
|
|
|
mov ecx, [user_command.size] ; ok now set the address
|
|
sub ecx, 8
|
|
|
|
mov esi, user_command+8
|
|
.now:
|
|
push esi
|
|
mov edi, irc_server_name
|
|
.loop: ; copy until zero byte, or ecx reaches zero.
|
|
lodsb
|
|
stosb
|
|
test al, al
|
|
jz .done
|
|
dec ecx
|
|
jnz .loop
|
|
xor al, al
|
|
stosb
|
|
.done:
|
|
pop esi
|
|
|
|
; set it also in window name
|
|
mov ebx, [window_print]
|
|
call window_set_name
|
|
|
|
; now connect
|
|
call socket_connect
|
|
|
|
ret
|
|
|
|
|
|
cmd_usr_quer:
|
|
|
|
mov esi, user_command+7
|
|
call window_open
|
|
; test ebx, ebx
|
|
; jz .fail
|
|
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_help:
|
|
|
|
mov esi, str_help
|
|
call print_asciiz
|
|
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_code:
|
|
|
|
; TODO
|
|
|
|
ret
|
|
|
|
|
|
|
|
; User typed a part command
|
|
cmd_usr_part:
|
|
|
|
cmp byte[user_command+5], 13 ; parameters given?
|
|
jne cmd_usr_send ; yes, send command straight to server
|
|
|
|
; close active window
|
|
cmd_usr_close_window:
|
|
|
|
mov esi, [window_active]
|
|
mov [window_print], esi
|
|
cmp [esi + window.type], WINDOWTYPE_SERVER
|
|
je .not_channel
|
|
|
|
lea esi, [esi + window.name]
|
|
call cmd_usr_part_channel
|
|
call window_close
|
|
ret
|
|
|
|
.not_channel:
|
|
cmp [esi + window.type], WINDOWTYPE_CHAT
|
|
jne .not_chat
|
|
|
|
call window_close
|
|
.not_chat:
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Send part command to server
|
|
; esi must point to channel name (ASCIIZ)
|
|
cmd_usr_part_channel:
|
|
|
|
; User wants to close a channel, send PART command to server
|
|
mov dword[packetbuf], 'PART'
|
|
mov byte[packetbuf+4], ' '
|
|
lea edi, [packetbuf+5]
|
|
@@:
|
|
lodsb
|
|
test al, al
|
|
jz @f
|
|
cmp al, 13
|
|
je @f
|
|
cmp al, 10
|
|
je @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
; end the command with a CRLF
|
|
mov ax, 0x0a0d
|
|
stosw
|
|
|
|
lea esi, [edi - packetbuf] ; calculate length
|
|
mcall send, [socketnum], packetbuf, , 0 ; and finally send to server
|
|
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_ctcp:
|
|
|
|
cmp byte[user_command+5], ' '
|
|
jne cmd_usr_send
|
|
|
|
mov esi, user_command+6
|
|
; prepare a 'PRIVMSG '
|
|
mov dword[packetbuf], 'PRIV'
|
|
mov dword[packetbuf+4], 'MSG '
|
|
lea edi, [packetbuf+8]
|
|
|
|
; append the destination (nickname/channel)
|
|
@@:
|
|
lodsb
|
|
test al, al
|
|
jz .fail
|
|
cmp al, ' '
|
|
je @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
|
|
mov ax, ' :'
|
|
stosw
|
|
mov al, 0x01
|
|
stosb
|
|
|
|
; copy the message itself
|
|
@@:
|
|
lodsb
|
|
test al, al
|
|
jz @f
|
|
cmp al, 13
|
|
je @f
|
|
cmp al, 10
|
|
je @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
|
|
; end of message
|
|
mov al, 0x01
|
|
stosb
|
|
mov ax, 0x0a0d
|
|
stosw
|
|
|
|
; now send it away
|
|
lea esi, [edi - packetbuf] ; calculate length
|
|
mcall send, [socketnum], packetbuf, , 0 ; and finally send to server
|
|
|
|
;; TODO: print to window
|
|
|
|
.fail:
|
|
|
|
ret
|
|
|
|
|
|
|
|
cmd_usr_me:
|
|
|
|
; prepare a 'PRIVMSG '
|
|
mov dword[packetbuf], 'PRIV'
|
|
mov dword[packetbuf+4], 'MSG '
|
|
lea edi, [packetbuf+8]
|
|
|
|
; append the destination (nickname/channel)
|
|
mov esi, [window_active]
|
|
lea esi, [esi + window.name]
|
|
@@:
|
|
lodsb
|
|
test al, al
|
|
je @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
|
|
; Make the CTCP action header
|
|
mov eax, ' :' + 0x01 shl 16 + 'A' shl 24
|
|
stosd
|
|
mov eax, 'CTIO'
|
|
stosd
|
|
mov al, 'N'
|
|
stosb
|
|
|
|
; copy the message itself (including first space)
|
|
mov esi, user_command+3
|
|
@@:
|
|
lodsb
|
|
cmp al, 13
|
|
je @f
|
|
stosb
|
|
jmp @r
|
|
@@:
|
|
|
|
; end of CTCP message
|
|
mov al, 0x01
|
|
stosb
|
|
mov ax, 0x0a0d
|
|
stosw
|
|
|
|
; now send it to the server
|
|
lea esi, [edi - packetbuf] ; calculate length
|
|
mcall send, [socketnum], packetbuf, , 0 ; and finally send to server
|
|
|
|
; print to local window
|
|
if TIMESTAMP
|
|
call print_timestamp
|
|
end if
|
|
|
|
mov esi, action_header
|
|
call print_asciiz
|
|
|
|
mov esi, user_nick
|
|
call print_asciiz
|
|
|
|
mov esi, user_command+3
|
|
mov bl, 13
|
|
call print_string
|
|
|
|
mov al, 10
|
|
call print_char
|
|
|
|
ret
|
|
|
|
|
|
|
|
; The user typed some undefined command, just send it to the server
|
|
cmd_usr_send:
|
|
|
|
mov esi, [user_command.size]
|
|
mov eax, [user_command.size]
|
|
add eax, user_command+1
|
|
mov word[eax], 0x0d0a
|
|
inc esi
|
|
mcall send, [socketnum], user_command+1, , 0
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|