From 5959abc989f0f3b9027a62bed1ab7edb73e35b46 Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Tue, 22 Jan 2013 14:05:00 +0000 Subject: [PATCH] Stub for new IRC client. git-svn-id: svn://kolibrios.org@3191 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../net/applications/ircc/encodings.inc | 317 +++++++ kernel/branches/net/applications/ircc/gui.inc | 241 +++++ .../branches/net/applications/ircc/ircc.asm | 449 +++++++++ .../branches/net/applications/ircc/ircc.ini | 8 + .../net/applications/ircc/serverparser.inc | 882 ++++++++++++++++++ .../branches/net/applications/ircc/socket.inc | 240 +++++ .../net/applications/ircc/userparser.inc | 313 +++++++ .../branches/net/applications/ircc/window.inc | 163 ++++ 8 files changed, 2613 insertions(+) create mode 100644 kernel/branches/net/applications/ircc/encodings.inc create mode 100644 kernel/branches/net/applications/ircc/gui.inc create mode 100644 kernel/branches/net/applications/ircc/ircc.asm create mode 100644 kernel/branches/net/applications/ircc/ircc.ini create mode 100644 kernel/branches/net/applications/ircc/serverparser.inc create mode 100644 kernel/branches/net/applications/ircc/socket.inc create mode 100644 kernel/branches/net/applications/ircc/userparser.inc create mode 100644 kernel/branches/net/applications/ircc/window.inc diff --git a/kernel/branches/net/applications/ircc/encodings.inc b/kernel/branches/net/applications/ircc/encodings.inc new file mode 100644 index 0000000000..220ef9ec2a --- /dev/null +++ b/kernel/branches/net/applications/ircc/encodings.inc @@ -0,0 +1,317 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +get_next_byte: +; Load next byte from the packet, translating to cp866 if necessary +; At input esi = pointer to data, edx = limit of data +; Output is either (translated) byte in al with CF set or CF cleared. + mov eax, [encoding] + jmp [get_byte_table+eax*4] + +get_byte_cp866: + cmp esi, edx + jae .nothing + lodsb +.nothing: + ret + +get_byte_cp1251: + cmp esi, edx + jae .nothing + lodsb + cmp al, 0x80 + jb @f + and eax, 0x7F + mov al, [cp1251_table+eax] +@@: + stc +.nothing: + ret + +get_byte_utf8: +; UTF8 decoding is slightly complicated. +; One character can occupy one or more bytes. +; The boundary in packets theoretically can be anywhere in data, +; so this procedure keeps internal state between calls and handles +; one byte at a time, looping until character is read or packet is over. +; Globally, there are two distinct tasks: decode byte sequence to unicode char +; and convert this unicode char to our base encoding (that is cp866). +; 1. Check that there are data. + cmp esi, edx + jae .nothing +; 2. Load byte. + lodsb + movzx ecx, al +; 3. Bytes in an UTF8 sequence can be of any of three types. +; If most significant bit is cleared, sequence is one byte and usual ASCII char. +; First byte of a sequence must be 11xxxxxx, other bytes are 10yyyyyy. + and al, 0xC0 + jns .single_byte + jp .first_byte +; 4. This byte is not first in UTF8 sequence. +; 4a. Check that the sequence was started. If no, it is invalid byte +; and we simply ignore it. + cmp [utf8_bytes_rest], 0 + jz get_byte_utf8 +; 4b. Otherwise, it is really next byte and it gives some more bits of char. + mov eax, [utf8_char] + shl eax, 6 + lea eax, [eax+ecx-0x80] +; 4c. Decrement number of bytes rest in the sequence. +; If it goes to zero, character is read, so return it. + dec [utf8_bytes_rest] + jz .got_char + mov [utf8_char], eax + jmp get_byte_utf8 +; 5. If the byte is first in UTF8 sequence, calculate the number of leading 1s +; - it equals total number of bytes in the sequence; some other bits rest for +; leading bits in the character. +.first_byte: + mov eax, -1 +@@: + inc eax + add cl, cl + js @b + mov [utf8_bytes_rest], eax + xchg eax, ecx + inc ecx + shr al, cl + mov [utf8_char], eax + jmp get_byte_utf8 +; 6. If the byte is ASCII char, it is the character. +.single_byte: + xchg eax, ecx +.got_char: +; We got the character, now abandon a possible sequence in progress. + and [utf8_bytes_rest], 0 +; Now second task. The unicode character is in eax, and now we shall convert it +; to cp866. + cmp eax, 0x80 + jb .done +; 0x410-0x43F -> 0x80-0xAF, 0x440-0x44F -> 0xE0-0xEF, 0x401 -> 0xF0, 0x451 -> 0xF1 + cmp eax, 0x401 + jz .YO + cmp eax, 0x451 + jz .yo + cmp eax, 0x410 + jb .unrecognized + cmp eax, 0x440 + jb .part1 + cmp eax, 0x450 + jae .unrecognized + sub al, (0x40-0xE0) and 0xFF + ret +.part1: + sub al, 0x10-0x80 +.nothing: +.done: + ret +.unrecognized: + mov al, '?' + stc + ret +.YO: + mov al, 0xF0 + stc + ret +.yo: + mov al, 0xF1 + stc + ret + + + +print_character: + + pusha + + cmp bl, 13 ; line beginning + jne nobol + + mov ecx, [pos] + inc ecx + boll1: + dec ecx + mov eax, ecx + xor edx, edx + mov ebx, [textbox_width] + div ebx + test edx, edx + jnz boll1 + mov [pos], ecx + jmp newdata + nobol: + + cmp bl, 10 ; line down + jne nolf + + addx1: + inc [pos] + mov eax, [pos] + xor edx, edx + mov ecx, [textbox_width] + div ecx + test edx, edx + jnz addx1 + mov eax, [pos] + jmp cm1 + nolf: + no_lf_ret: + + + cmp bl, 15 ; character + jbe newdata + + mov eax, [irc_data] + shl eax, 8 + mov al, bl + mov [irc_data], eax + + mov eax, [pos] + ;---- draw data + pusha + + and ebx, 0xff + add eax, [text_start] + mov [eax], bl + + popa + ;---- draw data + + mov eax, [pos] + inc eax + cm1: + mov ebx, [scroll+4] + imul ebx, [textbox_width] + cmp eax, ebx + jb noeaxz + + mov esi, [text_start] + add esi, [textbox_width] + + mov edi, [text_start] + mov ecx, ebx + rep movsb + + mov esi, [text_start] + mov ecx, [textbox_width] + imul ecx, 61 + add esi, ecx + + mov edi, [text_start] + mov ecx, [textbox_width] + imul ecx, 60 + add edi, ecx + mov ecx, ebx + rep movsb + + mov eax, ebx + sub eax, [textbox_width] + noeaxz: + mov [pos], eax + + newdata: + mov eax, [window_print] + or [eax + window.flags], FLAG_UPDATED + + popa + ret + + + +recode_to_cp866: + rep movsb + ret + +recode_to_cp1251: + xor eax, eax + jecxz .nothing + .loop: + lodsb + cmp al,0x80 + jb @f + mov al, [cp866_table-0x80+eax] + @@: stosb + loop .loop + .nothing: + ret + +recode_to_utf8: + jecxz .nothing + .loop: + lodsb + cmp al, 0x80 + jb .single_byte + and eax, 0x7F + mov ax, [utf8_table+eax*2] + stosw + loop .loop + ret + .single_byte: + stosb + loop .loop + .nothing: + ret + +recode: + mov eax, [encoding] + jmp [recode_proc+eax*4] + + + +encoding dd UTF8 +recode_proc dd recode_to_cp866, recode_to_cp1251, recode_to_utf8 +get_byte_table dd get_byte_cp866, get_byte_cp1251, get_byte_utf8 + + +cp1251_table: + db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; 8 + db '?','?','?','?','?',$F9,'?','?' , '?','?','?','?','?','?','?','?' ; 9 + db '?',$F6,$F7,'?',$FD,'?','?','?' , $F0,'?',$F2,'?','?','?','?',$F4 ; A + db $F8,'?','?','?','?','?','?',$FA , $F1,$FC,$F3,'?','?','?','?',$F5 ; B + db $80,$81,$82,$83,$84,$85,$86,$87 , $88,$89,$8A,$8B,$8C,$8D,$8E,$8F ; C + db $90,$91,$92,$93,$94,$95,$96,$97 , $98,$99,$9A,$9B,$9C,$9D,$9E,$9F ; D + db $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7 , $A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF ; E + db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; F + +; 0 1 2 3 4 5 6 7 8 9 A B C D E F + +utf8_table: + times 80h dw 0x98C3 ; default placeholder + +; 0x80-0xAF -> 0x90D0-0xBFD0 +repeat 0x30 + store byte 0xD0 at utf8_table+2*(%-1) + store byte 0x90+%-1 at utf8_table+2*%-1 +end repeat + +; 0xE0-0xEF -> 0x80D1-0x8FD1 +repeat 0x10 + store byte 0xD1 at utf8_table+2*(0xE0-0x80+%-1) + store byte 0x80+%-1 at utf8_table+2*(0xE0-0x80+%)-1 +end repeat + +; 0xF0 -> 0x81D0, 0xF1 -> 0x91D1 + store dword 0x91D181D0 at utf8_table+2*(0xF0-0x80) + +cp866_table: + db $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 , $C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ; 8 + db $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7 , $D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF ; 9 + db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; A + db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; B + db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; C + db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; D + db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7 , $F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF ; E + db $A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2 , $B0,$95,$B7,'?',$B9,$A4,'?','?' ; F + +; 0 1 2 3 4 5 6 7 8 9 A B C D E F + diff --git a/kernel/branches/net/applications/ircc/gui.inc b/kernel/branches/net/applications/ircc/gui.inc new file mode 100644 index 0000000000..c595ec2a52 --- /dev/null +++ b/kernel/branches/net/applications/ircc/gui.inc @@ -0,0 +1,241 @@ +draw_window: + + pusha + + mcall 9, thread_info, -1 ; get current window size + mov eax, dword[thread_info+42] ; window xsize + mov ebx, dword[thread_info+46] ; ysize + mov edx, dword[thread_info+62] ; work area xsize + mov esi, dword[thread_info+66] ; ysize + sub eax, edx + sub ebx, esi + + cmp edx, WIN_MIN_X + jae .x_ok + mov edx, WIN_MIN_X + .x_ok: + mov [xsize], edx + add edx, eax + + cmp esi, WIN_MIN_Y + jae .y_ok + mov esi, WIN_MIN_Y + .y_ok: + mov [ysize], esi + add esi, ebx + mcall 67, -1, -1 ; set the new sizes + + mcall 12, 1 + xor eax, eax ; draw window + mov ebx, WIN_MIN_X + mov ecx, WIN_MIN_Y + mov edx, [colors.work] + add edx, 0x33000000 + mov edi, str_programname + mcall + + mov ebx, [xsize] + mov ecx, [ysize] + sub cx, 35 + push cx + shl ecx, 16 + pop cx + mov edx, [colors.work_graph] + mcall 38 ; draw line + + mov ecx, TOP_Y SHL 16 + TOP_Y + mcall + + mov edi, [window_open] + cmp [edi + window.type], WINDOWTYPE_CHANNEL + jne .not_channel + + mov ebx, [xsize] + sub ebx, 100 + push bx + shl ebx, 16 + pop bx + mov ecx, [ysize] + add ecx, TOP_Y SHL 16 -(15+20) + mcall + + call print_channel_list + + .not_channel: + + mov edx, [edi + window.data_ptr] + add edx, window_data.text + call draw_channel_text + +; editbox + + mov eax, [ysize] + sub eax, 30 ;;;;;; + mov [edit1.top], eax + + mov eax, [xsize] + sub eax, 10 ;;;;;; + mov [edit1.width], eax + + push dword edit1 + call [edit_box_draw] + +; scrollbar + + mov eax, [ysize] + sub eax, TOP_Y + 35 ;;;; + mov [scroll1.y_size], ax + + mov eax, [xsize] + sub eax, SCROLLBAR_WIDTH + mov [scroll1.x_pos], ax + + mov [scroll1.all_redraw], 1 + + push dword scroll1 + call [scrollbar_v_draw] + + call draw_windownames + + mcall 12, 2 + popa + ret + + + +print_channel_list: + + pusha + + mov eax, 13 ; draw rectangle (clear list) + + mov ebx, [xsize] + sub ebx, 95 + shl ebx, 16 + push ebx + mov bx, 90 ; x size ;;; FIXME + mov ecx, TEXT_Y shl 16 + 12*10 ; y size ;;; FIXME + mov edx, [colors.work] + mcall + + mov eax, 4 ; draw text + pop ebx + mov bx, TEXT_Y + mov ecx, [colors.work_text] + or ecx, 0x80000000 ; ASCIIZ string + mov edx, [window_open] + mov edx, [edx + window.data_ptr] + add edx, window_data.names + mov edi, MAX_CHANNELS + .loop: + mcall + + add edx, MAX_NICK_LEN ; next name + add ebx, 10 ; height distance between lines + dec edi + jnz .loop + + popa + + ret + + + + +draw_channel_text: + + pusha + + mov eax, 4 ; draw text + mov ebx, TEXT_X shl 16 + TEXT_Y + mov ecx, 12 ; 12 lines max ? + mov esi, [textbox_width] + + .dct: + pusha + mov cx, bx + shl ecx, 16 + mov cx, 9 ; character height + mov eax, 13 ; draw rectangle + mov ebx, TEXT_X shl 16 + mov bx, word[textbox_width] + imul bx, 6 ; character width + mov edx, [colors.work] + mcall + popa + + push ecx + mov ecx, [colors.work_text] + cmp word[edx], '* ' + jne .no_red + mov ecx, 0x00aa0000 + jmp .draw + .no_red: + + cmp word[edx], '**' + jne .no_light_blue + cmp byte[edx+2], '*' + jne .no_light_blue + mov ecx, 0x000000aa + jmp .draw + .no_light_blue: + + cmp byte[edx], '#' + jne .no_blue + mov ecx, 0x0000aa00 +; jmp .draw + .no_blue: + + .draw: + mcall + add edx, [textbox_width] + add ebx, 10 ; height distance between lines + + pop ecx + loop .dct + + popa + ret + + + +draw_windownames: + + mov eax, 8 + mov ebx, 5 shl 16 + 120 + mov ecx, 12 shl 16 + 12 + mov edx, WINDOW_BTN_START + mov edi, windows + .more_btn: + mov esi, [colors.work_button] + cmp [window_open], edi + jne @f + not esi + and esi, 0x00ffffff + @@: + mcall + inc edx + add ebx, 125 shl 16 + add edi, sizeof.window + cmp [edi + + window.data_ptr], 0 + jne .more_btn + + mov eax, 4 + mov ebx, 10 shl 16 + 15 + mov ecx, [colors.work_button_text] + or ecx, 0x80000000 ; ASCIIZ string + lea edx, [windows + window.name] + mov esi, MAX_WINDOWS + .more: + mcall + add edx, sizeof.window + cmp byte[edx], 0 + je .enough + add ebx, 125 shl 16 + dec esi + jnz .more + .enough: + + ret + + diff --git a/kernel/branches/net/applications/ircc/ircc.asm b/kernel/branches/net/applications/ircc/ircc.asm new file mode 100644 index 0000000000..6856fd21f6 --- /dev/null +++ b/kernel/branches/net/applications/ircc/ircc.asm @@ -0,0 +1,449 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; IRC client for KolibriOS ;; +;; ;; +;; Written by hidnplayr@kolibrios.org, ;; +;; text encoder/decoder by Clevermouse. ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +version equ '0.1' + +; connection status +STATUS_DISCONNECTED = 0 +STATUS_RESOLVING = 1 +STATUS_CONNECTING = 2 +STATUS_CONNECTED = 3 + +; window flags +FLAG_UPDATED = 1 shl 0 +FLAG_CLOSE = 1 shl 1 + +; window types +WINDOWTYPE_SERVER = 0 +WINDOWTYPE_CHANNEL = 1 +WINDOWTYPE_CHAT = 2 +WINDOWTYPE_LIST = 3 +WINDOWTYPE_DCC = 4 + +; supported encodings +CP866 = 0 +CP1251 = 1 +UTF8 = 2 + +; settings +USERCMD_MAX_SIZE = 400 + +WIN_MIN_X = 600 +WIN_MIN_Y = 200 + +TEXT_X = 5 +TEXT_Y = 45 + +TOP_Y = 40 + +MAX_WINDOWS = 20 + +MAX_NICK_LEN = 32 +MAX_REAL_LEN = 32 ; realname +MAX_SERVER_NAME = 256 + +MAX_CHANNEL_LEN = 40 +MAX_CHANNELS = 37 + +MAX_COMMAND_LEN = 512 + +TIMESTAMP = 3 ; 3 = hh:mm:ss, 2 = hh:mm, 0 = no timestamp + +MAX_WINDOWNAME_LEN = 256 + +WINDOW_BTN_START = 100 + +SCROLLBAR_WIDTH = 12 + + +format binary as "" + +use32 + + org 0x0 + + db 'MENUET01' ; 8 byte id + dd 1 ; header version + dd START ; program start + dd I_END ; program image size + dd IM_END+2048 ; required amount of memory + dd IM_END+2048 + dd 0 + dd path + +include "../macros.inc" +include "../proc32.inc" +include "../dll.inc" +include "../network.inc" +include "../struct.inc" +include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac' + +struct window + data_ptr dd ? ; zero if not used + flags db ? + type db ? + name rb MAX_WINDOWNAME_LEN +ends + +struct window_data + text rb 120*60 + title rb 256 + names rb 1200 + namespos dd ? + usertext rb 256 + usertextlen dd ? +ends + +include "encodings.inc" +include "window.inc" ; also contains text print routines +include "serverparser.inc" +include "userparser.inc" +include "socket.inc" +include "gui.inc" + + +START: + + mcall 68, 11 ; init heap so we can allocate memory dynamically + +; wanted events + mcall 40, EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_STACK + EVM_MOUSE + +; load libraries + stdcall dll.Load, @IMPORT + test eax, eax + jnz exit + +; find path to main settings file (ircc.ini) + mov edi, path ; Calculate the length of zero-terminated string + xor al, al + mov ecx, 1024 + repne scasb + dec edi + mov eax, '.ini' + stosd + xor al, al + stosb + +; Fill the window buffer with zeros + mov edi, windows + mov ecx, (sizeof.window*MAX_WINDOWS+3)/4 + xor eax, eax + rep stosd + +; clear command area too + mov edi, servercommand + mov ecx, 600/4 + rep stosd + +; allocate window data block + + call window_create + mov ebx, windows + mov [ebx + window.data_ptr], eax + mov [ebx + window.flags], 0 + mov [ebx + window.type], WINDOWTYPE_SERVER + add eax, window_data.text + mov [text_start], eax + + call window_refresh + +; get system colors + mcall 48, 3, colors, 40 + +; set edit box and scrollbar colors + + mov eax, [colors.work] + mov [scroll1.bg_color], eax + + mov eax, [colors.work_button] + mov [scroll1.front_color], eax + + mov eax, [colors.work_text] + mov [scroll1.line_color], eax + +; get settings from ini + invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick + invoke ini.get_str, path, str_user, str_real, user_real_name, MAX_REAL_LEN, default_real + +; Welcome user + mov esi, str_welcome + call print_text2 + + call draw_window ;;; FIXME (gui is not correctly drawn first time) + +redraw: + call draw_window + +still: + +; wait here for event + mcall 10 + + dec eax + jz redraw + + dec eax + jz main_window_key + + dec eax + jz button + + cmp al, 3 + je mouse + + call process_network_event + + mov edx, [window_open] + test [edx + window.flags], FLAG_UPDATED + jz .no_update + and [edx + window.flags], not FLAG_UPDATED + mov edx, [edx + window.data_ptr] + add edx, window_data.text + call draw_channel_text + .no_update: + call print_channel_list + + jmp still + +button: + + mcall 17 ; get id + shr eax, 8 + + cmp ax, 1 ; close program + je exit + + sub ax, WINDOW_BTN_START + jb exit + + cmp ax, MAX_WINDOWS + ja exit + + mov dx, sizeof.window + mul dx + shl edx, 16 + mov dx, ax + add edx, windows + cmp [edx + window.data_ptr], 0 + je exit + mov [window_open], edx + call window_refresh + call draw_window + + jmp still +exit: + mcall -1 + + + +main_window_key: + + mcall 2 + + push dword edit1 + call [edit_box_key] + + cmp ah, 13 ; enter + jne no_send2 + + call user_parser + + mov [edit1.size], 0 + mov [edit1.pos], 0 + + push dword edit1 + call [edit_box_draw] + + mov edx, [window_open] + mov edx, [edx + window.data_ptr] + add edx, window_data.text + call draw_channel_text + + jmp still + no_send2: + + jmp still + +mouse: + push dword edit1 + call [edit_box_mouse] + + push dword scroll1 + call [scrollbar_v_mouse] + + jmp still + + +; DATA AREA + +encoding_text: +db 'CP866 ' +db 'CP1251' +db 'UTF-8 ' +encoding_text_len = 6 + +action_header db '*** ', 0 +action_header_short db '* ', 0 +ctcp_header db '-> [',0 +ctcp_version db '] VERSION',10,0 +ctcp_ping db '] PING',10,0 +ctcp_time db '] TIME',10,0 +has_left_channel db ' has left ', 0 +joins_channel db ' has joined ', 0 +is_now_known_as db ' is now known as ', 0 +has_quit_irc db ' has quit IRC', 0 +sets_mode db ' sets mode ', 0 +kicked db ' is kicked from ', 0 +str_talking db 'Now talking in ',0 +str_topic db 'Topic is ',0 +str_setby db 'Set by ',0 + +str_version db 'VERSION ' +str_programname db 'KolibriOS IRC client ', version, 0 + +str_user db 'user', 0 +str_nick db 'nick', 0 +str_real db 'realname', 0 +str_email db 'email', 0 + +default_nick db 'kolibri_user', 0 +default_real db 'Kolibri User', 0 + +str_welcome db 10 + db '.______________________ .__ .__ __',10 + db '| \______ \_ ___ \ ____ | | |__| ____ _____/ |_',10 + db '| || _/ \ \/ _/ ___\| | | |/ __ \ / \ __\',10 + db '| || | \ \____ \ \___| |_| \ ___/| | \ |',10 + db '|___||____|_ /\______ / \___ >____/__|\___ >___| /__|',10 + db ' \/ \/ \/ \/ \/',10 + db 10 + db 'Welcome to IRC client ',version,' for KolibriOS',10 + db 10 + db 'Type /help for help',10,0 + +str_nickchange db 10,'Nickname is now ',0 +str_realchange db 10,'Real name is now ',0 +str_dotnewline db '.',10, 0 +str_newline db 10, 0 +str_connecting db 10,'* Connecting to ',0 +str_help db 10,'following commands are available:',10 + db 10 + db '/nick : change nickname to ',10 + db '/real : change real name to ',10 + db '/server
: connect to server
',10 + db '/code : change codepage to cp866, cp1251, or utf8',10,0 + +str_1 db ' -',0 +str_2 db '- ',0 + +str_sockerr db 'Socket Error',10,0 +str_dnserr db 'Unable to resolve hostname.',10,0 +str_refused db 'Connection refused',10,0 + +sockaddr1: + dw AF_INET4 +.port dw 0x0b1a ; 6667 +.ip dd 0 + rb 10 + + +status dd STATUS_DISCONNECTED + +channel_line_sun dd 0x9999ff +channel_line_shadow dd 0x666699 +index_list_2 dd 0x0000ff + +text_start dd ? ; pointer to current textbox data +irc_data dd 0x0 ; encoder +textbox_width dd 80 ; in characters, not pixels ;) +pos dd 66 * 11 ; encoder + +window_open dd windows +window_print dd windows + +scroll dd 1 + dd 12 + +align 4 +@IMPORT: + +library network, 'network.obj',\ + libini, 'libini.obj',\ + boxlib, 'box_lib.obj' + +import network,\ + getaddrinfo, 'getaddrinfo',\ + freeaddrinfo, 'freeaddrinfo',\ + inet_ntoa, 'inet_ntoa' + +import libini,\ + ini.get_str, 'ini_get_str',\ + ini.get_int, 'ini_get_int' + +import boxlib,\ + edit_box_draw ,'edit_box' ,\ + edit_box_key ,'edit_box_key' ,\ + edit_box_mouse ,'edit_box_mouse' ,\ + scrollbar_v_draw ,'scrollbar_v_draw' ,\ + scrollbar_v_mouse,'scrollbar_v_mouse' + + +usercommand db '/server chat.freenode.net', 0 + rb MAX_COMMAND_LEN + +I_END: + + ; width, left, top +edit1 edit_box 0, 5, 0, 0xffffff, 0x6f9480, 0, 0, 0, USERCMD_MAX_SIZE, usercommand, mouse_dd, ed_focus, 25, 25 + ; xsize, xpos, ysize, ypos, max, cur, pos, bgcol, frcol, linecol +scroll1 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 5 + + +main_PID dd ? ; identifier of main thread +utf8_bytes_rest dd ? ; bytes rest in current UTF8 sequence +utf8_char dd ? ; first bits of current UTF8 character +gai_reqdata rb 32 ; buffer for getaddrinfo_start/process +ip_list dd ? ; will be filled as pointer to addrinfo list +packetbuf rb 1024 ; buffer for packets to server +path rb 1024 + +socketnum dd ? + +servercommand rb 600 + +thread_info rb 1024 +xsize dd ? +ysize dd ? + +colors system_colors + +irc_server_name rb MAX_SERVER_NAME + +user_nick rb MAX_NICK_LEN +user_real_name rb MAX_REAL_LEN + +windows rb MAX_WINDOWS*sizeof.window + +mouse_dd dd ? + +IM_END: + + + + + + + diff --git a/kernel/branches/net/applications/ircc/ircc.ini b/kernel/branches/net/applications/ircc/ircc.ini new file mode 100644 index 0000000000..6232627005 --- /dev/null +++ b/kernel/branches/net/applications/ircc/ircc.ini @@ -0,0 +1,8 @@ +[user] +nick = kolibri_user +realname = tetten + +[colors] +action1 = 0x000000aa +action2 = 0x0000aa00 +action3 = 0x00aa0000 \ No newline at end of file diff --git a/kernel/branches/net/applications/ircc/serverparser.inc b/kernel/branches/net/applications/ircc/serverparser.inc new file mode 100644 index 0000000000..088b8cf372 --- /dev/null +++ b/kernel/branches/net/applications/ircc/serverparser.inc @@ -0,0 +1,882 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +server_parser: + + mov esi, servercommand + + cmp byte [esi], ':' + jne .parse + + .spaceloop: + lodsb + test al, al + jz .fail + cmp al, ' ' + jne .spaceloop + + .parse: + mov eax, [esi] + or eax, 0x20202020 + mov edi, server_commands + mov ecx, server_commands.number + + .loop: + scasd + je .got_cmd + add edi, 4 + dec ecx + jnz .loop + + .fail: + ret + + .got_cmd: + jmp dword[edi+4] + + +server_commands: + + dd '328 ', cmd_328 + dd '332 ', cmd_topic + dd '333 ', cmd_333 ; nickname and time of topic + dd '353 ', cmd_353 ; name reply + dd '366 ', cmd_366 ; end of names list + dd '372 ', cmd_372 ; motd + dd '375 ', cmd_375 ; start of motd + dd '376 ', cmd_376 ; end of motd + dd '421 ', cmd_421 ; unknown command + dd 'join', cmd_join + dd 'kick', cmd_kick + dd 'mode', cmd_mode + dd 'nick', cmd_nick + dd 'part', cmd_part + dd 'ping', cmd_ping + dd 'priv', cmd_privmsg + dd 'quit', cmd_quit + dd 'noti', cmd_notice + + .number = ($ - server_commands) / 8 + +compare_to_nick: + + push esi + mov ecx, MAX_NICK_LEN + mov esi, user_nick + .loop: + lodsb + cmp al, ' ' + jbe .done + cmp al, 'a' + jb .ok + cmp al, 'z' + ja .ok + sub al, 0x20 + .ok: + + mov bl, byte[edi] + cmp bl, 'a' + jb .ok2 + cmp bl, 'z' + ja .ok2 + sub bl, 0x20 + .ok2: + cmp bl, al + jne .not_equal + inc edi + dec ecx + jnz .loop + + .done: + xor eax, eax + pop esi + ret + + .not_equal: + or eax, -1 + pop esi + ret + + + +find_window: + +; mov [window_print], + + ret + + + +cmd_328: +cmd_421: +cmd_372: +cmd_375: +cmd_376: + add esi, 4 + jmp cmd_notice.loop + +cmd_notice: + + cmp byte[servercommand], ':' + jne .gogogo + + mov byte [esi-1], 0 + push esi + mov esi, str_1 + call print_text2 + mov esi, servercommand+1 + call print_text2 + mov esi, str_2 + call print_text2 + pop esi + + .gogogo: + add esi, 6 + + .loop: + inc esi + cmp byte [esi], 0 + je .fail + cmp byte [esi], 10 ; newline + je server_parser.parse + cmp byte [esi], ' ' + jne .loop + + .loop2: + inc esi + cmp byte [esi], 0 + je .fail + cmp byte [esi], ' ' + je .loop2 + cmp byte [esi], ':' + je .loop2 + + call print_text2 + mov esi, str_newline + call print_text2 + + .fail: + + ret + + + +cmd_ping: + +; Just change PING to PONG + mov dword[esi], 'PONG' + +; Find the end of the command + lea edi, [esi + 5] + xor al, al + repne scasb + +; Now send it back + mov edx, esi + mov esi, edi + mov word [esi], 0x0d0a + inc esi + inc esi + sub esi, edx + mcall send, [socketnum], , , 0 + + ret + + + +cmd_privmsg: + +; Check if it was destined for me privately + mov edi, servercommand+1 + call compare_to_nick +;;; je .private + +; If not, find the correct window ??? + +; now find the end of nick + mov edi, esi + .loop: + inc edi + cmp byte [edi], 0 + je .fail + cmp byte [edi], ' ' + jne .loop + + .loop2: + inc edi + cmp byte [edi], 0 + je .fail + cmp byte [edi], ' ' + je .loop2 + cmp byte [edi], ':' + je .loop2 + cmp byte [edi], 1 + je cmd_ctcp + +; Action? + cmp dword[edi+1], 'ACTI' + je .action + +; nope, just plain old privmsg +if TIMESTAMP + call print_timestamp +end if + + push edi + mov bl, '<' + call print_character + + mov eax, servercommand+1 + mov dl, '!' + call print_text + + mov bl, '>' + call print_character + + mov bl, ' ' + call print_character + + pop esi + call print_text2 + + mov bl, 10 + call print_character + + .fail: + ret + + .action: + push edi + if TIMESTAMP + call print_timestamp + end if + + mov esi, action_header_short + call print_text2 + + mov eax, servercommand+1 + mov dl, ' ' + call print_text + + mov bl, ' ' + call print_character + + pop esi + add esi, 8 + call print_text2 + + mov bl, 10 + call print_character + + ret + +cmd_ctcp: + + cmp dword[edi+1], 'VERS' + je .version + + cmp dword[edi+1], 'TIME' + je .time + + cmp dword[edi+1], 'PING' + je .ping + + ret + + .time: + lea esi, [edi+1] + mov byte [edi+5], ' ' + add edi, 6 + + ; TODO: add system date (fn 29) in human readable format + + mcall 3 ; get system time + + mov ecx, 3 + .timeloop: + mov bl, al + shr al, 4 + add al, '0' + stosb + + mov al, bl + and al, 0x0f + add al, '0' + stosb + + dec ecx + jz .timedone + + mov al, ':' + stosb + shr eax, 8 + jmp .timeloop + + .timedone: + xor al, al + stosb + call ctcp_reply + + if TIMESTAMP + call print_timestamp + end if + + mov esi, ctcp_header + call print_text2 + + mov esi, servercommand+1 + call print_text2 + + mov esi, ctcp_time + call print_text2 + + ret + + .version: + mov esi, str_version + call ctcp_reply + + if TIMESTAMP + call print_timestamp + end if + + mov esi, ctcp_header + call print_text2 + + mov esi, servercommand+1 + call print_text2 + + mov esi, ctcp_version + call print_text2 + + ret + + .ping: + lea esi, [edi+1] + call ctcp_reply + + if TIMESTAMP + call print_timestamp + end if + + mov esi, ctcp_header + call print_text2 + + mov esi, servercommand+1 + call print_text2 + + mov esi, ctcp_ping + call print_text2 + + ret + + + +ctcp_reply: + + push esi + + mov dword [usercommand], 'NOTI' + mov dword [usercommand+4], 'CE ' + + mov esi, servercommand+1 + mov edi, usercommand+7 + .nickloop: + lodsb + cmp al, '!' + je .done + cmp al, ' ' + je .done + test al, al + je .fail + stosb + jmp .nickloop + .done: + mov byte [esi-1], 0 + mov ax, ' :' + stosw + mov al, 1 + stosb + + pop esi + .replyloop: + lodsb + cmp al, 1 + jbe .done2 + stosb + jmp .replyloop + .done2: + + mov al, 1 + stosb + mov ax, 0x0a0d + stosw + + lea esi, [edi - usercommand] + mcall send, [socketnum], usercommand, , 0 + .fail: + ret + + + +cmd_part: + +; Is it me who parted? + mov edi, servercommand+1 + call compare_to_nick + jne .dont_close + +; yes, close the window + mov edi, [window_print] + mov [edi + window.flags], FLAG_UPDATED + FLAG_CLOSE + + ret + +; somebody else parted, just print message + .dont_close: + push esi + mov esi, action_header + call print_text2 + + mov eax, servercommand+1 + mov dl, '!' + mov cl, ' ' + call print_text + + mov esi, has_left_channel + call print_text2 + + pop esi + call print_text2 + + ret + + + +cmd_join: +; compare nick: did we join a channel? + mov edi, servercommand+1 + call compare_to_nick + jne .no_new_window + +; create channel window - search for empty slot + mov ebx, windows + mov ecx, MAX_WINDOWS + .loop: + cmp [ebx + window.data_ptr], 0 + je .free_found + add ebx, sizeof.window + dec ecx + jnz .loop +; Error: no more available windows!! ;;;;; TODO + .fail: + ret + + .free_found: + push ebx + call window_create + pop ebx + test eax, eax + jz .fail + mov [ebx + window.data_ptr], eax + mov [ebx + window.type], WINDOWTYPE_CHANNEL + mov [ebx + window.flags], 0 + call window_set_name + + mov [window_open], ebx + mov [window_print], ebx + call window_refresh + + push esi + mov esi, action_header + call print_text2 + + mov esi, str_talking + call print_text2 + + pop eax + mov dl, ' ' + call print_text + + mov esi, str_dotnewline + call print_text2 + + call draw_window + + ret + + .no_new_window: + push esi + call window_set_name + + mov esi, action_header + call print_text2 + + mov eax, servercommand+1 + mov dl, ' ' + call print_text + + mov esi, joins_channel + call print_text2 + + pop esi + call print_text2 + + mov esi, str_newline + call print_text2 + + ret + + + + +cmd_nick: ; FIXME + + push esi +; test for change of my nick + mov esi, servercommand+1 + mov edi, user_nick + mov ecx, MAX_NICK_LEN + rep cmpsb + cmp byte[edi-1], 0 + jne .notmy + cmp byte[esi-1], '!' + jne .notmy + +; yes, this is my nick, set to new + pop esi + or ecx, -1 + mov edi, esi + xor eax, eax + repne scasb + neg ecx + cmp ecx, MAX_NICK_LEN + jb @f + mov ecx, MAX_NICK_LEN + @@: + mov edi, user_nick + rep movsb + .notmy: + +; replace nick in all lists of users + mov ebx, windows + .channels: + mov esi, [ebx + window.data_ptr] + lea esi, [esi + window_data.names] +;;;;; mov edx, [esi + window_data.nameslen] + add edx, esi + .nicks: + mov edi, servercommand+1 + cmp byte[esi], '@' + jne @f + inc esi + + @@: + cmp esi, edx + jae .srcdone + lodsb + cmp al, ' ' + je .srcdone + scasb + je @b + + @@: + cmp esi, edx + jae .nextchannel + lodsb + cmp al, ' ' + jne @b + + .nextnick: + cmp esi, edx + jae .nextchannel + lodsb + cmp al, ' ' + jz .nextnick + dec esi + jmp .nicks + + + .srcdone: + cmp byte [edi], '!' + jne .nextnick + +; here we have esi -> end of nick which must be replaced to [servercommand_position]+6 + lea edx, [edi-servercommand-1] + sub esi, edx + or ecx, -1 + xor eax, eax +; mov edi, [servercommand_position] ;;;;; FIXME + repnz scasb + not ecx + dec ecx + push ecx + cmp ecx, edx + jb .decrease + jz .copy + .increase: + +; new nick is longer than the old + push esi + lea edi, [ebx+120*10] ;;;;;; + lea esi, [edi+edx] + sub esi, ecx + mov ecx, esi + sub ecx, [esp] + dec esi + dec edi + std + rep movsb + cld + pop esi + jmp .copy + .decrease: +; new nick is shorter than the old + push esi + lea edi, [esi+ecx] + add esi, edx + lea ecx, [ebx+120*10] + sub ecx, edi + rep movsb + pop esi + .copy: +; copy nick + mov edi, esi + dec edi +; mov esi, [servercommand_position] ;;;;; FIXME + pop ecx + sub edx, ecx + sub [ebx-4], edx + rep movsb + mov al, ' ' + stosb + + .nextchannel: + add ebx, sizeof.window + cmp ebx, windows + sizeof.window*MAX_WINDOWS + jb .channels + +; mov [text_start], window_text + 120*80 + new_all_channels3: + + mov esi, action_header_short + call print_text2 + + mov eax, servercommand+1 + mov dl,'!' + call print_text + + mov esi,is_now_known_as + call print_text2 + +; mov esi,[servercommand_position] ;;;;; FIXME + call print_text2 + +;;; call notify_channel_thread + +; go to next window (and check if its a channel!) + +; add [text_start], 120*80 +; cmp [text_start], I_END+120*80*20 +; jb new_all_channels3 + + ret + + + + +cmd_kick: +; Is it me who got kicked? + mov edi, servercommand+1 + call compare_to_nick + jne .not_me + +; TODO: mark channel as disconnected + + .not_me: +; find the channel user has been kicked from + push esi + mov esi, action_header_short + call print_text2 + + mov eax, servercommand+1 + mov dl,'!' + call print_text + + mov esi, kicked + call print_text2 + + pop esi + call print_text2 + + ret + + + +cmd_quit: + + mov esi, action_header + call print_text2 + + mov eax, servercommand+1 + mov dl, '!' + call print_text + + mov esi, has_quit_irc + call print_text2 + + ret + + + +cmd_mode: + + push esi + mov esi, action_header_short + call print_text2 + + mov eax, servercommand+1 + mov dl, ' ' + call print_text + + mov esi, sets_mode + call print_text2 + + pop esi + call print_text2 + + mov esi, str_newline + call print_text2 + + ret + + +cmd_353: ; channel usernames reply + +; TODO: mark a bit that we are receiving names + +; first, find the channel name + .loop1: + lodsb + cmp al, '#' + je .got_channel + test al, al + jnz .loop1 + + ret + + .got_channel: +; call find_channel ;;;; ASSUME current channel for now + mov ebx, [window_print] + mov ebx, [ebx + window.data_ptr] + lea edi, [ebx + window_data.names] + lea edx, [edi + MAX_NICK_LEN] + +; now find the semicolon separating channelname and usernames + .loop2: + lodsb + cmp al, ':' + je .namesloop + test al, al + jnz .loop2 + + ret + + .namesloop: +; now the names list begins, separated with spaces + lodsb + test al, al + jz .done + cmp al, ' ' + jz .next + stosb + jmp .namesloop + + .next: + mov edi, edx + add edx, MAX_NICK_LEN + +;;; cmp edi, .. ; Check for buffer overflow + jmp .namesloop + + .done: + call print_channel_list + + ret + + + + +cmd_366: ; channel usernames end + +; TODO: clear the bit that we are receiving names + + + ret + + +cmd_topic: + + .loop: + lodsb + test al, al + je .fail + cmp al, ':' + jne .loop + + push esi + mov esi, action_header + call print_text2 + + mov esi, str_topic + call print_text2 + + pop esi + call print_text2 + + mov esi, str_newline + call print_text2 + + .fail: + ret + + +cmd_333: + +; TODO: check channelname and change pointer accordingly + + mov ecx, 3 ; number of spaces to find + .loop: + lodsb + test al, al + je .fail + cmp al, ' ' + jne .loop + dec ecx + jnz .loop ; find some more spaces + + push esi + mov esi, action_header + call print_text2 + + mov esi, str_setby + call print_text2 + + pop esi + call print_text2 + + mov esi, str_newline + call print_text2 + + .fail: + ret + diff --git a/kernel/branches/net/applications/ircc/socket.inc b/kernel/branches/net/applications/ircc/socket.inc new file mode 100644 index 0000000000..72036bdb87 --- /dev/null +++ b/kernel/branches/net/applications/ircc/socket.inc @@ -0,0 +1,240 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +socket_connect: + +; cmp [status], STATUS_CONNECTED ; TODO +; je disconnect + +; ignore if status is not "disconnected" + cmp [status], STATUS_DISCONNECTED + jne .nothing + + mov esi, str_connecting + call print_text2 + mov esi, irc_server_name + call print_text2 + mov esi, str_dotnewline + call print_text2 + +; update status + inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING + +; resolve name + push esp ; reserve stack place + push esp ; fourth parameter + push 0 ; third parameter + push 0 ; second parameter + push irc_server_name + call [getaddrinfo] + pop esi +; test for error + test eax, eax + jnz .fail_dns + +; fill in ip in sockstruct + mov eax, [esi + addrinfo.ai_addr] + mov eax, [eax + sockaddr_in.sin_addr] + mov [sockaddr1.ip], eax + +; free allocated memory + push esi + call [freeaddrinfo] + +; update status + inc [status] + +; connect + mcall socket, AF_INET4, SOCK_STREAM, 0 + cmp eax, -1 + jz .fail + mov [socketnum], eax + + mcall connect, [socketnum], sockaddr1, 18 + cmp eax, -1 + jz .fail_refused + + .nothing: + ret + + .fail: + mov [status], STATUS_DISCONNECTED + + mov esi, str_sockerr + call print_text2 + + ret + + .fail_dns: + mov [status], STATUS_DISCONNECTED + + mov esi, str_dnserr + call print_text2 + + ret + + .fail_refused: + mov [status], STATUS_DISCONNECTED + + mov esi, str_refused + call print_text2 + + ret + + + +socket_write_userinfo: + +; create packet in packetbuf + mov edi, packetbuf + + mov eax, 'NICK' + stosd + mov al, ' ' + stosb + mov esi, user_nick + mov ecx, MAX_NICK_LEN + .loop: + lodsb + test al, al + jz .done + stosb + dec ecx + jnz .loop + .done: + mov ax, 0x0d0a + stosw + + mov eax, 'USER' + stosd + mov al, ' ' + stosb + mov esi, user_nick + mov ecx, MAX_NICK_LEN + .loop2: + lodsb + test al, al + jz .done2 + stosb + dec ecx + jnz .loop2 + .done2: + mov eax, ' 8 *' + stosd + mov ax, ' :' + stosw + mov al, ' ' + stosb + mov esi, user_real_name + mov ecx, MAX_REAL_LEN + .loop3: + lodsb + test al, al + jz .done3 + stosb + dec ecx + jnz .loop3 + .done3: + mov ax, 0x0d0a + stosw + + lea esi, [edi - packetbuf] + mcall send, [socketnum], packetbuf, , 0 + + ret + + + + +process_network_event: +; values for status: 0, 1, 2, 3 + mov eax, [status] + dec eax +; 0 = STATUS_DISCONNECTED - do nothing +; (ignore network events if we are disconnected from network) + js .nothing +; 1 = STATUS_RESOLVING + jz .nothing +; 2 = STATUS_CONNECTING + dec eax + jz .connecting +; 3 = STATUS_CONNECTED + jmp .connected + + .nothing: + ret + + .connecting: + call socket_write_userinfo + +; The connection has been established, change status from "connecting" to "connected". + inc [status] + + .connected: + call read_incoming_data + ret + + +disconnect: + + cmp [status], STATUS_DISCONNECTED + je .nothing + + mcall close, [socketnum] + + mov [status], STATUS_DISCONNECTED + + .nothing: + ret + + + +read_incoming_data: + + pusha + +; TODO: read more data if we receive one full packet + + .nextpacket: + mcall recv, [socketnum], packetbuf, 1024 ; read a packet + inc eax ; check if we got one + jz .done + dec eax + jz .done + +; ok we have data, now feed it to the recoder + + lea edx, [packetbuf + eax] ; edx = end pointer + mov esi, packetbuf ; esi = start pointer + .nextcommand: + mov edi, servercommand + .byteloop: + call get_next_byte ; reads byte from [esi] to al + jnc .nextpacket ; if CF is set, we need more data + cmp al, 10 + je .got_command + stosb + jmp .byteloop + +; we have a command, call the serverparser + + .got_command: + mov byte[edi-1], 0 ; mark the end of the command + push esi edx + call server_parser + pop edx esi + jmp .nextcommand + + .done: + popa + + ret \ No newline at end of file diff --git a/kernel/branches/net/applications/ircc/userparser.inc b/kernel/branches/net/applications/ircc/userparser.inc new file mode 100644 index 0000000000..4eb571bfb1 --- /dev/null +++ b/kernel/branches/net/applications/ircc/userparser.inc @@ -0,0 +1,313 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +user_parser: + + mov eax, [edit1.size] + mov word [usercommand + eax], 0x0a0d ; terminate the line + + cmp byte[usercommand], '/' ; is it a server command ? + je server_command + +; Ignore data commands when not connected. + cmp [status], STATUS_CONNECTED + jne sdts_ret + +; Ok, we said something, print it to our textbox + + if TIMESTAMP + call print_timestamp + end if + + mov bl, '<' + call print_character + + mov esi, user_nick + call print_text2 + + mov bl,'>' + call print_character + mov bl,' ' + call print_character + + mov eax, [edit1.size] + mov byte[usercommand + eax],0 + + mov esi, usercommand + call print_text2 + + mov bl, 10 + call print_character + +; and now send it to the server + + mov dword[packetbuf], 'priv' + mov dword[packetbuf+4], 'msg ' + + mov esi, [window_print] + add esi, 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, usercommand + mov ecx, [edit1.size] + inc ecx + call recode + + mov al, 10 + stosb + + lea esi, [edi - packetbuf] + mcall send, [socketnum], packetbuf, , 0 + +sdts_ret: + + ret + + + +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 +; TODO: All other commands require a connection to the server. + dd 'quer', cmd_usr_quer + dd 'quit', cmd_usr_quit + + .number = ($ - user_commands) / 8 + + + +server_command: + + mov eax, dword[usercommand+1] + or eax, 0x20202020 + + mov edi, user_commands + mov ecx, user_commands.number + .loop: + scasd + je .got_cmd + add edi, 4 + dec ecx + jnz .loop + jmp cmd_usr_send ; If none of the previous commands, just send to server + + .got_cmd: + jmp dword[edi] + + + + + +cmd_usr_quit: + + cmp [edit1.size], 5 + je .ok + jb cmd_usr_send + cmp byte[usercommand+5], ' ' + jne cmd_usr_send + + .ok: + call cmd_usr_send + + mcall close, [socketnum] + + mov ecx, MAX_WINDOWS + mov edi, windows + .loop: + mov [edi+window.flags], FLAG_CLOSE +; call notify_channel_thread + add edi, sizeof.window + dec ecx + jnz .loop + + ret + + + + +cmd_usr_nick: + + cmp [edit1.size], 5 + je .justprint + cmp byte[usercommand+5], ' ' + jne cmd_usr_send + + mov ecx, MAX_NICK_LEN + mov esi, usercommand+6 + mov edi, user_nick + .loop: + lodsb + cmp al, 13 + je .done + stosb + dec ecx + jnz .loop + .done: + xor al, al + stosb + + cmp [socketnum], 0 + je .justprint + + lea esi, [edi - usercommand] + mcall send, [socketnum], usercommand+1, , 0 + + .justprint: + mov esi, str_nickchange + call print_text2 + mov esi, user_nick + call print_text2 + mov esi, str_dotnewline + call print_text2 + + ret + + + +cmd_usr_real: + + cmp byte[usercommand+5], ' ' + jne cmd_usr_send + + mov ecx, MAX_REAL_LEN + mov esi, usercommand+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_text2 + mov esi, user_real_name + call print_text2 + mov esi, str_dotnewline + call print_text2 + + ret + + + +cmd_usr_server: + + mov eax, dword[usercommand+5] ; check for 'er ', we only checked 'serv' + or eax, 0x00002020 + and eax, 0x00ffffff + cmp eax, 'er ' + jne cmd_usr_send + + mov ecx, [edit1.size] ; ok now set the address + sub ecx, 8 + + mov esi, usercommand+8 + push esi + mov edi, irc_server_name + rep movsb + xor al, al + stosb + 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 ecx, MAX_WINDOWS + mov ebx, windows + .loop: + cmp [ebx + window.data_ptr], 0 + je .found + add ebx, sizeof.window + dec ecx + jnz .loop + +; error: no available channels ! FIXME + + ret + + + .found: + call window_create + test eax, eax + jz .error + mov [ebx + window.data_ptr], eax + + mov esi, usercommand+7 + call window_set_name + + mov [ebx + window.type], WINDOWTYPE_CHAT + mov [ebx + window.flags], 0 + + .error: + + ret + + + +cmd_usr_help: + + mov esi, str_help + call print_text2 + + ret + + + +cmd_usr_code: + + ; TODO + + ret + + + +cmd_usr_send: + + mov esi, usercommand+1 + mov ecx, [edit1.size] + inc ecx + mov edi, packetbuf + call recode + + lea esi, [edi - packetbuf] + mcall send, [socketnum], packetbuf, , 0 + + ret + diff --git a/kernel/branches/net/applications/ircc/window.inc b/kernel/branches/net/applications/ircc/window.inc new file mode 100644 index 0000000000..abbc6aecc6 --- /dev/null +++ b/kernel/branches/net/applications/ircc/window.inc @@ -0,0 +1,163 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +window_create: + +; allocate the window data block + mcall 68, 12, sizeof.window_data + test eax, eax + jz .fail + +; fill it with all zeros + push eax + mov edi, eax + mov ecx, (sizeof.window_data+3)/4 + xor eax, eax + rep stosd + pop eax + + .fail: + ret + + +window_set_name: ; esi = ptr to name, ebx = window ptr + + pusha + +; Skip heading spaces + .spaceloop: + cmp byte[esi], ' ' + jne .done + inc esi + jmp .spaceloop + .done: + +; Now copy it + lea edi, [ebx + window.name] + mov ecx, MAX_WINDOWNAME_LEN + .loop: + lodsb + cmp al, 10 + jbe .addzero + stosb + dec ecx + jnz .loop + .addzero: + xor al, al + stosb + + call draw_windownames ; redraw it + + popa + + ret + + + +window_find: ; esi is ptr to windowname + +; mov [current_window], +; call reset_gui + + .fail: + ret + + + + +window_refresh: + +; set the correct buffer pointers ; FIXME: what is it good for? + mov eax, [textbox_width] ; + imul eax, 11 ; + mov [pos], eax ; + + mov eax, [window_open] + mov eax, [eax + window.data_ptr] + add eax, window_data.text + mov [text_start], eax + + ret + + +print_text: ; eax = start ptr + ; dl = end char + pusha + ptr2: + mov bl, [eax] + + cmp bl, dl + je ptr_ret + cmp bl, 0 + je ptr_ret + call print_character + + inc eax + jmp ptr2 + + ptr_ret: + popa + ret + + +print_text2: ; esi = ptr to ASCIIZ string + + pusha + .loop: + lodsb + test al, al + jz .done + mov bl, al + call print_character + jmp .loop + + .done: + popa + ret + + +if TIMESTAMP +print_timestamp: + + pusha + mcall 3 ; get system time + + mov bl, '[' + call print_character + mov ecx, TIMESTAMP + .loop: + mov bl, al + shr bl, 4 + add bl, '0' + call print_character + + mov bl, al + and bl, 0x0f + add bl, '0' + call print_character + + dec ecx + jz .done + + mov bl, ':' + call print_character + shr eax, 8 + jmp .loop + .done: + mov bl, ']' + call print_character + mov bl, ' ' + call print_character + + popa + ret +end if \ No newline at end of file