Subversion Repositories Kolibri OS

Rev

Rev 6027 | Rev 9092 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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