Subversion Repositories Kolibri OS

Rev

Rev 7300 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;   Written by hidnplayr@kolibrios.org                            ;;
  7. ;;                                                                 ;;
  8. ;;         GNU GENERAL PUBLIC LICENSE                              ;;
  9. ;;          Version 2, June 1991                                   ;;
  10. ;;                                                                 ;;
  11. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  12.  
  13.  
  14. server_parser:
  15.  
  16.         mov     esi, servercommand
  17.  
  18.         cmp     byte [esi], ':'
  19.         jne     .parse
  20.  
  21.   .spaceloop:
  22.         lodsb
  23.         test    al, al
  24.         jz      .fail
  25.         cmp     al, ' '
  26.         jne     .spaceloop
  27.  
  28.   .parse:
  29.         mov     eax, [esi]
  30.         or      eax, 0x20202020
  31.         mov     edi, server_commands
  32.         mov     ecx, server_commands.number
  33.  
  34.   .loop:
  35.         scasd
  36.         je      .got_cmd
  37.         add     edi, 4
  38.         dec     ecx
  39.         jnz     .loop
  40.  
  41.   .fail:
  42.         ret
  43.  
  44.   .got_cmd:
  45.         jmp     dword[edi]
  46.  
  47.  
  48. server_commands:
  49.  
  50.         dd      '001 ', cmd_welcome
  51.         dd      '002 ', cmd_justprint
  52.         dd      '003 ', cmd_justprint
  53.         dd      '004 ', cmd_justprint
  54.         dd      '005 ', cmd_justprint
  55.  
  56.         dd      '250 ', cmd_justprint
  57.         dd      '251 ', cmd_justprint
  58.         dd      '252 ', cmd_justprint
  59.         dd      '253 ', cmd_justprint
  60.         dd      '254 ', cmd_justprint
  61.         dd      '255 ', cmd_justprint
  62.  
  63.         dd      '265 ', cmd_justprint
  64.         dd      '266 ', cmd_justprint
  65.  
  66.         dd      '311 ', cmd_justprint   ; RPL_WHOISUSER
  67.         dd      '312 ', cmd_justprint   ; RPL_WHOISSERVER
  68.         dd      '317 ', cmd_justprint   ; RPL_WHOISIDLE
  69.         dd      '318 ', cmd_justprint   ; RPL_ENDOFWHOIS
  70.         dd      '319 ', cmd_justprint   ; RPL_WHOISCHANNELS
  71.         dd      '322 ', cmd_322         ; RPL_LIST
  72.         dd      '323 ', cmd_323         ; RPL_LISTEND
  73.         dd      '324 ', cmd_justprint   ; RPL_CHANNELMODEIS
  74.         dd      '328 ', cmd_justprint   ; RPL_CHANNEL_URL
  75.         dd      '329 ', cmd_justprint   ; RPL_CREATIONTIME
  76.         dd      '330 ', cmd_justprint
  77.         dd      '332 ', cmd_topic       ; topic
  78.         dd      '333 ', cmd_333         ; nickname and time of topic
  79.         dd      '338 ', cmd_justprint   ; RPL_CHANPASSOK
  80.         dd      '353 ', cmd_353         ; name reply
  81.         dd      '366 ', cmd_366         ; end of names list
  82.         dd      '372 ', cmd_justprint   ; motd
  83.         dd      '375 ', cmd_justprint   ; start of motd
  84.         dd      '376 ', cmd_justprint   ; end of motd
  85.         dd      '421 ', cmd_justprint   ; unknown command
  86.         dd      '432 ', cmd_justprint   ; erroneous nickname
  87.         dd      '433 ', cmd_justprint   ; nickname already in use
  88.         dd      '436 ', cmd_justprint   ; nickname collision
  89.         dd      '671 ', cmd_justprint   ; RPL_WHOISSECURE
  90.  
  91.         dd      'join', cmd_join
  92.         dd      'kick', cmd_kick
  93.         dd      'mode', cmd_mode
  94.         dd      'nick', cmd_nick
  95.         dd      'part', cmd_part
  96.         dd      'ping', cmd_ping
  97.         dd      'priv', cmd_privmsg
  98.         dd      'quit', cmd_quit
  99.         dd      'noti', cmd_notice
  100.  
  101.         .number = ($ - server_commands) / 8
  102.  
  103.  
  104. align 4
  105. compare_to_nick:
  106.  
  107.         push    esi
  108.         mov     ecx, MAX_NICK_LEN
  109.         mov     esi, user_nick
  110.   .loop:
  111.         lodsb
  112.         cmp     al, ' '
  113.         jbe     .done
  114.         test    al, al
  115.         jz      .done
  116.         cmp     al, 'a'
  117.         jb      .ok
  118.         cmp     al, 'z'
  119.         ja      .ok
  120.         sub     al, 0x20
  121.   .ok:
  122.  
  123.         mov     bl, byte[edi]
  124.         cmp     bl, 'a'
  125.         jb      .ok2
  126.         cmp     bl, 'z'
  127.         ja      .ok2
  128.         sub     bl, 0x20
  129.   .ok2:
  130.         cmp     bl, al
  131.         jne     .not_equal
  132.         inc     edi
  133.         dec     ecx
  134.         jnz     .loop
  135.  
  136.   .done:
  137.         xor     eax, eax
  138.         pop     esi
  139.         ret
  140.  
  141.   .not_equal:
  142.         or      eax, -1
  143.         pop     esi
  144.         ret
  145.  
  146.  
  147.  
  148. align 4
  149. skip_parameter:
  150.  
  151. ; First: skip the parameter (scan untill space or colon)
  152.   .part1:
  153.         lodsb
  154.         cmp     al, ' '
  155.         je      .part2
  156.         cmp     al, ':'
  157.         jne     .part1
  158.  
  159. ; Skip all trailing spaces
  160.   .part3:
  161.         lodsb
  162.         cmp     al, ' '
  163.         je      .part3
  164.         dec     esi
  165.         ret
  166.  
  167. ; Now, skip all trailing spaces and first semicolon
  168.   .part2:
  169.         lodsb
  170.         cmp     al, ' '
  171.         je      .part2
  172.         cmp     al, ':'
  173.         je      .part3
  174.         dec     esi
  175.         ret
  176.  
  177.  
  178.  
  179. cmd_welcome:
  180.  
  181.         mov     [status], STATUS_LOGGED_IN
  182.  
  183. cmd_justprint:
  184.  
  185.         add     esi, 4
  186.         call    skip_parameter          ; our nickname
  187.  
  188.         call    print_asciiz
  189.  
  190.         mov     al, 10
  191.         call    print_char
  192.  
  193.         ret
  194.  
  195.  
  196.  
  197. cmd_notice:
  198.  
  199.         if TIMESTAMP
  200.         call    print_timestamp
  201.         end if
  202.  
  203.         cmp     byte[servercommand], ':'
  204.         jne     .gogogo
  205.  
  206.         mov     byte [esi-1], 0
  207.         push    esi
  208.         mov     esi, str_1
  209.         call    print_asciiz
  210.         mov     esi, servercommand+1
  211.         mov     bl, '!'
  212.         call    print_string
  213.         mov     esi, str_2
  214.         call    print_asciiz
  215.         pop     esi
  216.  
  217.   .gogogo:
  218.         add     esi, 6
  219.         call    skip_parameter
  220.         call    skip_parameter
  221.         call    print_asciiz
  222.  
  223.         mov     al, 10
  224.         call    print_char
  225.  
  226.         ret
  227.  
  228.  
  229.  
  230. cmd_ping:
  231.  
  232. ; Just change PING to PONG
  233.         mov     dword[esi], 'PONG'
  234.  
  235. ; Find the end of the command
  236.         lea     edi, [esi + 5]
  237.         xor     al, al
  238.         repne   scasb
  239.  
  240. ; Now send it back
  241.         mov     edx, esi
  242.         mov     esi, edi
  243.         mov     word [esi], 0x0d0a
  244.         inc     esi
  245.         inc     esi
  246.         sub     esi, edx
  247.         mcall   send, [socketnum], , , 0
  248.  
  249.         ret
  250.  
  251.  
  252.  
  253. cmd_privmsg:
  254.  
  255.         mov     eax, dword[esi+4]
  256.         or      eax, 0x20202020
  257.         cmp     eax, 'msg '
  258.         jne     .fail
  259.         add     esi, 8          ; skip 'PRIVMSG '
  260.  
  261.         mov     edi, esi
  262.         call    compare_to_nick
  263.         jne     .channel
  264.  
  265. ; private chat message
  266.         push    esi
  267.         mov     esi, servercommand+1
  268.         call    window_open
  269.         test    ebx, ebx
  270.         jz      .fail2
  271.         pop     esi
  272.         call    skip_parameter  ; our own nickname
  273.         jmp     .print
  274.  
  275.   .channel:
  276.         call    window_open
  277.         test    ebx, ebx
  278.         jz      .fail
  279.  
  280.   .print:
  281.         cmp     byte[esi], 1    ; Client to Client protocol?
  282.         je      cmd_ctcp
  283.  
  284.         if TIMESTAMP
  285.         call    print_timestamp
  286.         end if
  287.  
  288.         push    esi
  289.         mov     al, '<'
  290.         call    print_char
  291.  
  292.         mov     esi, servercommand+1
  293.         mov     bl, '!'
  294.         call    print_string
  295.  
  296.         mov     al, '>'
  297.         call    print_char
  298.  
  299.         mov     al, ' '
  300.         call    print_char
  301.  
  302.         pop     esi
  303.         call    print_asciiz
  304.  
  305.         mov     al, 10
  306.         call    print_char
  307.  
  308.         ret
  309.  
  310.   .fail2:
  311.         pop     esi
  312.   .fail:
  313.         ret
  314.  
  315.  
  316.  
  317.  
  318. cmd_ctcp:
  319.  
  320.         inc     esi
  321.         mov     eax, dword[esi]
  322.         or      eax, 0x20202020
  323.  
  324.         cmp     eax, 'vers'
  325.         je      .version
  326.         cmp     eax, 'time'
  327.         je      .time
  328.         cmp     eax, 'ping'
  329.         je      .ping
  330.         cmp     eax, 'acti'
  331.         je      .action
  332.         cmp     eax, 'dcc '    ; TODO
  333.         je      cmd_dcc
  334.  
  335. ; Unknown CTCP command - just print to window
  336.  
  337.   .just_print:
  338.  
  339.         push    esi
  340.  
  341.         if TIMESTAMP
  342.         call    print_timestamp
  343.         end if
  344.  
  345.         mov     esi, ctcp_header_recv
  346.         call    print_asciiz
  347.  
  348.         mov     al, '<'
  349.         call    print_char
  350.  
  351.         mov     esi, servercommand+1    ; print nickname
  352.         mov     bl, '!'
  353.         call    print_string
  354.  
  355.         mov     al, '>'
  356.         call    print_char
  357.  
  358.         mov     al, ' '
  359.         call    print_char
  360.  
  361.         pop     esi
  362.         mov     bl, 1
  363.         call    print_string
  364.  
  365.         mov     al, 10
  366.         call    print_char
  367.  
  368.         ret
  369.  
  370.   .time:
  371.         mov     byte[esi+4], ' '
  372.         lea     edi, [esi+5]
  373.  
  374.         ; TODO: add system date (fn 29) in human readable format
  375.  
  376.         mcall   3                       ; get system time
  377.  
  378.         mov     ecx, 3
  379.   .timeloop:
  380.         mov     bl, al
  381.         shr     al, 4
  382.         add     al, '0'
  383.         stosb
  384.  
  385.         mov     al, bl
  386.         and     al, 0x0f
  387.         add     al, '0'
  388.         stosb
  389.  
  390.         dec     ecx
  391.         jz      .timedone
  392.  
  393.         mov     al, ':'
  394.         stosb
  395.         shr     eax, 8
  396.         jmp     .timeloop
  397.  
  398.   .timedone:
  399.         xor     al, al
  400.         stosb
  401.         call    ctcp_reply
  402.  
  403.         if TIMESTAMP
  404.         call    print_timestamp
  405.         end if
  406.  
  407.         mov     esi, ctcp_header
  408.         call    print_asciiz
  409.  
  410.         mov     esi, servercommand+1
  411.         call    print_asciiz
  412.  
  413.         mov     esi, ctcp_time
  414.         call    print_asciiz
  415.  
  416.         ret
  417.  
  418.   .version:
  419.         mov     esi, str_version
  420.         call    ctcp_reply
  421.  
  422.         if TIMESTAMP
  423.         call    print_timestamp
  424.         end if
  425.  
  426.         mov     esi, ctcp_header
  427.         call    print_asciiz
  428.  
  429.         mov     esi, servercommand+1
  430.         call    print_asciiz
  431.  
  432.         mov     esi, ctcp_version
  433.         call    print_asciiz
  434.  
  435.         ret
  436.  
  437.   .ping:
  438.         call    ctcp_reply
  439.  
  440.         if TIMESTAMP
  441.         call    print_timestamp
  442.         end if
  443.  
  444.         mov     esi, ctcp_header
  445.         call    print_asciiz
  446.  
  447.         mov     esi, servercommand+1
  448.         call    print_asciiz
  449.  
  450.         mov     esi, ctcp_ping
  451.         call    print_asciiz
  452.  
  453.         ret
  454.  
  455.   .action:
  456.         add     esi, 7
  457.         push    esi
  458.  
  459.         if TIMESTAMP
  460.         call    print_timestamp
  461.         end if
  462.  
  463.         mov     esi, action_header
  464.         call    print_asciiz
  465.  
  466.         mov     esi, servercommand+1    ; print nickname
  467.         mov     bl, '!'
  468.         call    print_string
  469.  
  470.         mov     al, ' '
  471.         call    print_char
  472.  
  473.         pop     esi
  474.         call    print_asciiz
  475.  
  476.         mov     al, 10
  477.         call    print_char
  478.  
  479.         ret
  480.  
  481.  
  482. cmd_dcc:
  483.         add     esi, 4
  484.         mov     eax, dword[esi]
  485.         or      eax, 0x202020
  486.  
  487.         cmp     eax, 'send'
  488.         je      .send
  489.  
  490.         ret
  491.  
  492.   .send:
  493.         call    window_open
  494.         test    ebx, ebx
  495.         jz      .fail
  496.         mov     [ebx + window.type], WINDOWTYPE_DCC
  497.  
  498.   .fail:
  499.  
  500.         ret
  501.  
  502.  
  503.  
  504. ctcp_reply:
  505.  
  506.         push    esi
  507.         mov     dword[user_command], 'NOTI'
  508.         mov     dword[user_command+4], 'CE  '
  509.  
  510.         mov     esi, servercommand+1
  511.         mov     edi, user_command+7
  512.   .nickloop:
  513.         lodsb
  514.         cmp     al, '!'
  515.         je      .done
  516.         cmp     al, ' '
  517.         je      .done
  518.         test    al, al
  519.         je      .fail
  520.         stosb
  521.         jmp     .nickloop
  522.   .done:
  523.         mov     byte [esi-1], 0
  524.         mov     ax, ' :'
  525.         stosw
  526.         mov     al, 1
  527.         stosb
  528.  
  529.         pop     esi
  530.   .replyloop:
  531.         lodsb
  532.         cmp     al, 1
  533.         jbe     .done2
  534.         stosb
  535.         jmp     .replyloop
  536.   .done2:
  537.  
  538.         mov     al, 1
  539.         stosb
  540.         mov     ax, 0x0a0d
  541.         stosw
  542.  
  543.         lea     esi, [edi - user_command]
  544.         mcall   send, [socketnum], user_command, , 0
  545.   .fail:
  546.         ret
  547.  
  548.  
  549.  
  550. cmd_part:
  551.  
  552.         cmp     byte [esi+4], ' '
  553.         jne     .fail
  554.         add     esi, 5  ; skip 'PART '
  555.  
  556. ; Is it me who parted?
  557.         mov     edi, servercommand+1
  558.         call    compare_to_nick
  559.         jne     .not_me
  560.  
  561. ; yes, close the window (if its open)
  562.         call    window_find
  563.         test    ebx, ebx
  564.         jz      @f
  565.         call    window_close
  566.   @@:
  567.   .fail:
  568.  
  569.         ret
  570.  
  571.  
  572. ; somebody else parted, just print message
  573.   .not_me:
  574.         push    esi
  575.         call    window_open
  576.         test    ebx, ebx
  577.         jz      .fail2
  578.  
  579.         if TIMESTAMP
  580.         call    print_timestamp
  581.         end if
  582.  
  583.         mov     esi, part_header
  584.         call    print_asciiz
  585.  
  586.         mov     esi, servercommand+1
  587.         mov     bl, '!'
  588.         call    print_string
  589.  
  590.         mov     esi, has_left_channel
  591.         call    print_asciiz
  592.  
  593.         pop     esi
  594.         call    print_asciiz
  595.  
  596.         mov     al, 10
  597.         call    print_char
  598.  
  599.         mov     ebx, [window_print]
  600.         mov     esi, servercommand+1
  601.         call    user_remove
  602.  
  603.         ret
  604.  
  605.   .fail2:
  606.         pop     esi
  607.  
  608.         ret
  609.  
  610.  
  611.  
  612. cmd_join:
  613.  
  614.         cmp     byte[esi+4], ' '
  615.         jne     .fail
  616.         add     esi, 5  ; skip 'JOIN '
  617.  
  618. ; did we join a channel?
  619.         mov     edi, servercommand+1
  620.         call    compare_to_nick
  621.         jne     .not_me
  622.  
  623.         push    esi
  624.         call    window_open
  625.         test    ebx, ebx
  626.         jz      .fail
  627.         mov     [ebx + window.type], WINDOWTYPE_CHANNEL
  628.         mov     [window_active], ebx
  629.  
  630.         if TIMESTAMP
  631.         call    print_timestamp
  632.         end if
  633.  
  634.         mov     esi, join_header
  635.         call    print_asciiz
  636.  
  637.         mov     esi, str_talking
  638.         call    print_asciiz
  639.  
  640.         pop     esi
  641.         mov     bl, ' '
  642.         call    print_string
  643.  
  644.         mov     al, 10
  645.         call    print_char
  646.  
  647.         call    draw_window
  648.  
  649.         ret
  650.  
  651.   .not_me:
  652.         push    esi
  653.         call    window_open
  654.         test    ebx, ebx
  655.         jz      .fail
  656.  
  657.         if TIMESTAMP
  658.         call    print_timestamp
  659.         end if
  660.  
  661.         mov     esi, join_header
  662.         call    print_asciiz
  663.  
  664.         mov     esi, servercommand+1
  665.         mov     bl, '!'
  666.         call    print_string
  667.  
  668.         mov     esi, joins_channel
  669.         call    print_asciiz
  670.  
  671.         pop     esi
  672.         call    print_asciiz
  673.  
  674.         mov     al, 10
  675.         call    print_char
  676.  
  677.         mov     ebx, [window_print]
  678.         mov     esi, servercommand+1
  679.         call    user_add
  680.  
  681.         ret
  682.  
  683.   .fail:
  684.         pop     esi
  685.         ret
  686.  
  687.  
  688.  
  689.  
  690. cmd_nick:
  691.  
  692.         cmp     byte[esi+4], ' '
  693.         jne     .fail
  694.         add     esi, 5          ; skip 'NICK '
  695.         cmp     byte[esi], ':'
  696.         jne     @f
  697.         inc     esi
  698.   @@:
  699.  
  700. ; Is it me who changed nick?
  701.         push    esi
  702.         mov     edi, servercommand+1
  703.         call    compare_to_nick
  704.         jne     .not_me
  705.  
  706. ; Yup, update user_nick
  707.         mov     ecx, MAX_NICK_LEN-1
  708.         mov     esi, [esp]
  709.         mov     edi, user_nick
  710.   @@:
  711.         lodsb
  712.         test    al, al
  713.         jz      @f
  714.         cmp     al, ' '
  715.         je      @f
  716.         cmp     al, 10
  717.         je      @f
  718.         cmp     al, 13
  719.         je      @f
  720.         cmp     al, ':'
  721.         je      @r
  722.         stosb
  723.         dec     ecx
  724.         jnz     @r
  725.   @@:
  726.         xor     al, al
  727.         stosb
  728.  
  729. ; Print a message on the server window
  730.         mov     [window_print], windows
  731.  
  732.         mov     esi, str_nickchange
  733.         call    print_asciiz
  734.  
  735.         mov     esi, user_nick
  736.         call    print_asciiz
  737.  
  738.         mov     al, 10
  739.         call    print_char
  740.  
  741.   .not_me:
  742.  
  743. ; Update in userlist
  744.         mov     ebx, windows
  745.         mov     ecx, MAX_WINDOWS
  746.   .window_loop:
  747.         push    ecx ebx
  748.         cmp     [ebx + window.type], WINDOWTYPE_CHANNEL
  749.         jne     .next_window
  750.  
  751.         mov     esi, servercommand+1
  752.         call    user_remove
  753.         test    edi, edi
  754.         jz      .next_window
  755.  
  756.         mov     esi, [esp + 8]
  757.         call    user_add
  758.  
  759. ; And print a notification in the channel
  760.         mov     [window_print], ebx
  761.  
  762.         if TIMESTAMP
  763.         call    print_timestamp
  764.         end if
  765.  
  766.         mov     esi, nick_header
  767.         call    print_asciiz
  768.  
  769.         mov     esi, servercommand+1
  770.         mov     bl, '!'
  771.         call    print_string
  772.  
  773.         mov     esi, is_now_known_as
  774.         call    print_asciiz
  775.  
  776.         mov     esi, [esp + 8]
  777.         call    print_asciiz
  778.  
  779.         mov     al, 10
  780.         call    print_char
  781.  
  782. ; Now do this for all open windows
  783.   .next_window:
  784.         pop     ebx ecx
  785.         add     ebx, sizeof.window
  786.         dec     ecx
  787.         jnz     .window_loop
  788.  
  789.         pop     esi
  790.  
  791.   .fail:
  792.  
  793.         ret
  794.  
  795.  
  796.  
  797.  
  798. cmd_kick:
  799.  
  800.         cmp     byte [esi+4], ' '
  801.         jne     .fail
  802.         add     esi, 5  ; skip 'KICK '
  803.  
  804. ; TODO: Is it me who got kicked?
  805. ; if so, mark channel as disconnected
  806.  
  807.   .not_me:
  808. ; find the channel user has been kicked from
  809.         push    esi
  810.         call    window_open
  811.         test    ebx, ebx
  812.         jz      .fail
  813.         push    esi
  814.  
  815.         if TIMESTAMP
  816.         call    print_timestamp
  817.         end if
  818.  
  819.         mov     esi, kick_header
  820.         call    print_asciiz
  821.  
  822.         pop     esi
  823.         mov     bl, ' '
  824.         call    print_string
  825.  
  826.         mov     esi, str_kicked
  827.         call    print_asciiz
  828.  
  829.         pop     esi
  830.         mov     bl, ' '
  831.         call    print_string
  832.  
  833.         mov     esi, str_by
  834.         call    print_asciiz
  835.  
  836.         mov     esi, servercommand+1
  837.         mov     bl, '!'
  838.         call    print_string
  839.  
  840.         mov     al, 10
  841.         call    print_char
  842.  
  843.         mov     ebx, [window_print]
  844.         mov     esi, servercommand+1
  845.         call    user_remove
  846.  
  847.         ret
  848.  
  849.   .fail:
  850.         pop     esi
  851.  
  852.         ret
  853.  
  854.  
  855.  
  856. cmd_quit:
  857.  
  858.         cmp     byte [esi+4], ' '
  859.         jne     .fail
  860.  
  861.         mov     ebx, windows
  862.         mov     ecx, MAX_WINDOWS
  863.  
  864.   .window_loop:
  865.         push    ecx
  866.         cmp     [ebx + window.type], WINDOWTYPE_CHANNEL
  867.         jne     .next_window
  868.  
  869.         mov     esi, servercommand+1
  870.         call    user_remove
  871.         test    edi, edi
  872.         jz      .next_window
  873.  
  874.         push    ebx
  875.         mov     [window_print], ebx
  876.  
  877.         if TIMESTAMP
  878.         call    print_timestamp
  879.         end if
  880.  
  881.         mov     esi, quit_header
  882.         call    print_asciiz
  883.  
  884.         mov     esi, servercommand+1
  885.         mov     bl, '!'
  886.         call    print_string
  887.  
  888.         mov     esi, has_quit_irc
  889.         call    print_asciiz
  890.  
  891. ; TODO: check if quit message was given, and print it to the window
  892.         pop     ebx
  893.   .next_window:
  894.         pop     ecx
  895.         add     ebx, sizeof.window
  896.         dec     ecx
  897.         jnz     .window_loop
  898.  
  899.   .fail:
  900.  
  901.  
  902.         ret
  903.  
  904.  
  905.  
  906. cmd_mode:
  907.  
  908.         cmp     byte [esi+4], ' '
  909.         jne     .fail
  910.         add     esi, 5  ; skip 'MODE '
  911.         push    esi
  912.         call    window_find
  913.         test    ebx, ebx
  914.         jz      .user
  915.         mov     [esp], esi
  916.         mov     [window_print], ebx
  917.  
  918.         if TIMESTAMP
  919.         call    print_timestamp
  920.         end if
  921.  
  922.         mov     esi, mode_header
  923.         call    print_asciiz
  924.  
  925.         mov     esi, servercommand+1
  926.         mov     bl, '!'
  927.         call    print_string
  928.  
  929.         mov     esi, sets_mode
  930.         call    print_asciiz
  931.  
  932.         pop     esi
  933.         call    print_asciiz
  934.  
  935.         mov     al, 10
  936.         call    print_char
  937.  
  938. ; TODO: keep track of user modes in username list
  939.  
  940.   .fail:
  941.         ret
  942.  
  943.  
  944.   .user:
  945.         if TIMESTAMP
  946.         call    print_timestamp
  947.         end if
  948.  
  949.         mov     esi, mode_header
  950.         call    print_asciiz
  951.  
  952.         mov     esi, [esp]
  953.         mov     bl, ' '
  954.         call    print_string
  955.  
  956.         mov     esi, sets_mode
  957.         call    print_asciiz
  958.  
  959.         pop     esi
  960.         call    skip_parameter
  961.         call    print_asciiz
  962.  
  963.         mov     al, 10
  964.         call    print_char
  965.  
  966.         ret
  967.  
  968.  
  969. cmd_353:                ; channel usernames reply
  970.  
  971.         add     esi, 4  ; skip '353 '
  972.         call    skip_parameter
  973.         inc     esi     ; channel type '*', '=' or '@'
  974.         inc     esi     ; ' '
  975.         call    window_open
  976.         test    ebx, ebx
  977.         jz      .fail
  978.  
  979. ; now find window ptr and check if this is the first 353 message
  980.         mov     ebx, [window_print]
  981.         test    [ebx + window.flags], FLAG_RECEIVING_NAMES
  982.         jnz     .add
  983.  
  984.         or      [ebx + window.flags], FLAG_RECEIVING_NAMES
  985. ;        mov     [ebx + window.users], 0
  986.         ; TODO: remove all users?
  987.  
  988.   .add:
  989.         push    esi
  990.         call    user_add
  991.         pop     esi
  992.  
  993.   .namesloop:
  994.         lodsb
  995.         test    al, al
  996.         jz      .done
  997.         cmp     al, ' '                 ; names list is separated with spaces
  998.         jne     .namesloop
  999.         jmp     .add
  1000.  
  1001.   .done:
  1002.         call    draw_user_list
  1003.   .fail:
  1004.  
  1005.         ret
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011. cmd_366:        ; channel usernames end
  1012.  
  1013.         add     esi, 4          ; skip '366 '
  1014.         call    skip_parameter
  1015.         call    window_open
  1016.         test    ebx, ebx
  1017.         jz      .fail
  1018.         and     [ebx + window.flags], not FLAG_RECEIVING_NAMES
  1019.   .fail:
  1020.  
  1021.         ret
  1022.  
  1023.  
  1024.  
  1025.  
  1026. cmd_topic:
  1027.  
  1028.         add     esi, 4          ; skip '332 '
  1029.         call    skip_parameter
  1030.         call    window_open
  1031.         test    ebx, ebx
  1032.         jz      .fail
  1033.  
  1034.         if TIMESTAMP
  1035.         call    print_timestamp
  1036.         end if
  1037.  
  1038.         push    esi
  1039.         mov     esi, topic_header
  1040.         call    print_asciiz
  1041.  
  1042.         mov     esi, str_topic
  1043.         call    print_asciiz
  1044.  
  1045.         pop     esi
  1046.         call    print_asciiz
  1047.  
  1048.         mov     esi, str_topic_end
  1049.         call    print_asciiz
  1050.  
  1051.   .fail:
  1052.  
  1053.         ret
  1054.  
  1055.  
  1056. cmd_333:
  1057.  
  1058.         add     esi, 4          ; skip '333 '
  1059.         call    skip_parameter
  1060.         call    window_open
  1061.         test    ebx, ebx
  1062.         jz      .fail
  1063.  
  1064.         if TIMESTAMP
  1065.         call    print_timestamp
  1066.         end if
  1067.  
  1068.         push    esi
  1069.         mov     esi, topic_header
  1070.         call    print_asciiz
  1071.  
  1072.         mov     esi, str_setby
  1073.         call    print_asciiz
  1074.  
  1075.         pop     esi
  1076.         mov     bl, '!'
  1077.         call    print_string
  1078.  
  1079.         mov     al, 10
  1080.         call    print_char
  1081.  
  1082.   .fail:
  1083.  
  1084.         ret
  1085.  
  1086.  
  1087.  
  1088. cmd_322:        ; LIST
  1089.  
  1090.         add     esi, 4
  1091.         call    skip_parameter
  1092.  
  1093.         push    esi
  1094.         mov     esi, str_list
  1095.         call    window_open
  1096.         test    ebx, ebx
  1097.         jz      .fail
  1098.  
  1099.         mov     [window_active], ebx
  1100.         call    draw_window_tabs
  1101.         pop     esi
  1102.         call    print_asciiz
  1103.         mov     al, 10
  1104.         call    print_char
  1105.  
  1106.         ret
  1107.  
  1108.   .fail:
  1109.         pop     esi
  1110.  
  1111.         ret
  1112.  
  1113. cmd_323:        ; LIST END
  1114.  
  1115.         ret