$ git clone http://tcclient.ion.nu/tc_client.git
commit 36e007dba62eb849d8fd28d472b2a9bd2f55c503
Author: Alicia <...>
Date:   Tue Apr 7 06:49:00 2015 +0200

    Version 0.7

diff --git a/ChangeLog b/ChangeLog
index 59b2dd1..6eaf8e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,12 @@
+0.7:
+Added command handling (/color <number>, /colors, /nick <newnick>, and adding the privacy field for /msg)
 0.6:
 Fixed a bug in the ID list that kept IDs from being removed correctly.
 Show colors using ANSI escape codes.
 0.5:
 Fixed a bug in irchack.c that sent the JOIN confirmation to the wrong file descriptor.
 Avoid sending empty lines.
-Handle messages related to getting kicked out/banned from a channel.
+Handle messages related to getting kicked out/banned from a channel. (contributed by Jade)
 0.4:
 Adjustments for portability: nested functions are a GCC extension and should not be used, include headers needed on other systems.
 Use memcpy in some places instead of *x=y and x=*y to avoid alignment issues.
diff --git a/Makefile b/Makefile
index dce00d7..75a8eb9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.6
+VERSION=0.7
 CFLAGS=-g3 -Wall $(shell curl-config --cflags)
 LIBS=-g3 $(shell curl-config --libs)
 
diff --git a/README b/README
index 01fabe8..897560f 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 Some notes about tc_client in its current state (things that should be fixed):
 *there is no real user interface, to send a message you just type it and it might get cut off by incoming messages, it'll be ugly. There is however the irchack program that lets you use an IRC client.
-*PMs can be sent by /msg <nickname> <message> and replies appear similarly. Note however that PMs sent this way are currently sent to everyone in the channel, but the flash client ignores them.
+*PMs can be sent by /msg <nickname> <message> and replies appear similarly.
 *you can't log in with an account and thus not do mod stuff, I don't know how this works protocol-wise
 
 Some things that will probably never change:
diff --git a/amfwriter.c b/amfwriter.c
index 23d2ffb..8dcd543 100644
--- a/amfwriter.c
+++ b/amfwriter.c
@@ -82,7 +82,7 @@ void amfbool(struct amfmsg* msg, char v)
   x[1]=!!v;
 }
 
-void amfstring(struct amfmsg* msg, char* string)
+void amfstring(struct amfmsg* msg, const char* string)
 {
   int len=strlen(string);
   int offset=sizeof(struct rtmph)+msg->len;
diff --git a/amfwriter.h b/amfwriter.h
index 329b4ae..3828ad0 100644
--- a/amfwriter.h
+++ b/amfwriter.h
@@ -25,7 +25,7 @@ extern void amfinit(struct amfmsg* msg);
 extern void amfsend(struct amfmsg* msg, int sock);
 extern void amfnum(struct amfmsg* msg, double v);
 extern void amfbool(struct amfmsg* msg, char v);
-extern void amfstring(struct amfmsg* msg, char* string);
+extern void amfstring(struct amfmsg* msg, const char* string);
 extern void amfobjstart(struct amfmsg* msg);
 extern void amfobjitem(struct amfmsg* msg, char* name);
 extern void amfobjend(struct amfmsg* msg);
diff --git a/client.c b/client.c
index ce84d08..97dfe99 100644
--- a/client.c
+++ b/client.c
@@ -164,7 +164,7 @@ int main(int argc, char** argv)
     return 1;
   }
   char* channel=argv[1];
-  char* nickname=argv[2];
+  char* nickname=strdup(argv[2]);
   char* password=(argc>3?argv[3]:0);
   char* server=gethost(channel, password);
   struct addrinfo* res;
@@ -187,6 +187,7 @@ int main(int argc, char** argv)
   // RTMP handshake
   unsigned char handshake[1536];
   read(random, handshake, 1536);
+  read(random, &currentcolor, sizeof(currentcolor));
   close(random);
   write(sock, "\x03", 1); // Send 0x03 and 1536 bytes of random junk
   write(sock, handshake, 1536);
@@ -273,6 +274,56 @@ int main(int argc, char** argv)
       while(len>0 && (buf[len-1]=='\n'||buf[len-1]=='\r')){--len;}
       if(!len){continue;} // Don't send empty lines
       buf[len]=0;
+      int privfield=-1;
+      int privlen;
+      if(buf[0]=='/') // Got a command
+      {
+        if(!strncmp((char*)buf, "/color", 6) && (!buf[6]||buf[6]==' '))
+        {
+          if(buf[6]) // Color specified
+          {
+            currentcolor=atoi((char*)&buf[7]);
+            printf("\x1b[%smChanged color\x1b[0m\n", termcolors[currentcolor%16]);
+          }else{ // No color specified, state our current color
+            printf("\x1b[%smCurrent color: %i\x1b[0m\n", termcolors[currentcolor%16], currentcolor%16);
+          }
+          fflush(stdout);
+          continue;
+        }
+        else if(!strcmp((char*)buf, "/colors"))
+        {
+          int i;
+          for(i=0; i<16; ++i)
+          {
+            printf("\x1b[%smColor %i\x1b[0m\n", termcolors[i], i);
+          }
+          fflush(stdout);
+          continue;
+        }
+        else if(!strncmp((char*)buf, "/nick ", 6))
+        {
+          free(nickname);
+          nickname=strdup((char*)&buf[6]);
+          amfinit(&amf);
+          amfstring(&amf, "nick");
+          amfnum(&amf, 0);
+          amfnull(&amf);
+          amfstring(&amf, nickname);
+          amfsend(&amf, sock);
+          continue;
+        }
+        else if(!strncmp((char*)buf, "/msg ", 5))
+        {
+          for(privlen=0; buf[5+privlen]&&buf[5+privlen]!=' '; ++privlen);
+          privfield=idlist_get((char*)&buf[5]);
+          if(privfield<0)
+          {
+            printf("No such nick\n");
+            fflush(stdout);
+            continue;
+          }
+        }
+      }
       len=mbstowcs(0, (char*)buf, 0);
       wchar_t wcsbuf[len+1];
       mbstowcs(wcsbuf, (char*)buf, len+1);
@@ -282,11 +333,16 @@ int main(int argc, char** argv)
       amfnum(&amf, 0);
       amfnull(&amf);
       amfstring(&amf, msg);
-      // amfstring(&amf, colors[currentcolor%16]); // Alternating colors, fun but annoying in the long run
-      amfstring(&amf, "#000000,en");
-// TODO: for PMs, add a string like "n<numeric ID>-<nick>" to avoid broadcasting private messages to everyone connected (although the flash client ignores PMs sent to others)
+      amfstring(&amf, colors[currentcolor%16]);
+      // For PMs, add a string like "n<numeric ID>-<nick>" to make the server only send it to the intended recipient
+      if(privfield>-1)
+      {
+        char priv[snprintf(0, 0, "n%i-", privfield)+privlen+1];
+        sprintf(priv, "n%i-", privfield);
+        strncat(priv, (char*)&buf[5], privlen);
+        amfstring(&amf, priv);
+      }
       amfsend(&amf, sock);
-      // ++currentcolor;
       free(msg);
       continue;
     }
diff --git a/colors.c b/colors.c
index 8967326..1114e67 100644
--- a/colors.c
+++ b/colors.c
@@ -56,6 +56,8 @@ const char* termcolors[]={
   "35;1"
 };
 
+unsigned int currentcolor;
+
 const char* resolvecolor(const char* tc_color)
 {
   int i;
diff --git a/colors.h b/colors.h
index 76c1f29..a57cee2 100644
--- a/colors.h
+++ b/colors.h
@@ -16,5 +16,6 @@
 */
 extern const char* colors[];
 extern const char* termcolors[];
+extern unsigned int currentcolor;
 
 extern const char* resolvecolor(const char* tc_color);
diff --git a/idlist.c b/idlist.c
index 297f3b1..da7a400 100644
--- a/idlist.c
+++ b/idlist.c
@@ -61,10 +61,12 @@ void idlist_rename(const char* oldname, const char* newname)
 
 int idlist_get(const char* name)
 {
+  int len;
+  for(len=0; name[len]&&name[len]!=' '; ++len);
   int i;
   for(i=0; i<idlistlen; ++i)
   {
-    if(!strcmp(name, idlist[i].name))
+    if(!strncmp(name, idlist[i].name, len) && !idlist[i].name[len])
     {
       return idlist[i].id;
     }
diff --git a/irchack.c b/irchack.c
index 4b022d9..7257bda 100644
--- a/irchack.c
+++ b/irchack.c
@@ -104,7 +104,6 @@ int main(int argc, char** argv)
   }
   close(tc_in[0]);
   close(tc_out[1]);
-  dprintf(sock, ":%s!user@host JOIN #%s\n", nick, channel);
   struct pollfd pfd[2];
   pfd[0].fd=tc_out[0];
   pfd[0].events=POLLIN;
@@ -126,6 +125,11 @@ int main(int argc, char** argv)
       }
       buf[len]=0;
 printf("Got from tc_client: '%s'\n", buf);
+      if(!strncmp(buf, "Guest ID: ", 10))
+      {
+        dprintf(sock, ":%s!user@host NICK :guest-%s\n", nick, &buf[10]);
+        continue;
+      }
       if(!strncmp(buf, "Currently online: ", 18))
       {
         dprintf(sock, ":irchack 353 %s = #%s :", nick, channel);
@@ -220,6 +224,12 @@ printf("Got from IRC client: '%s'\n", buf);
           dprintf(tc_in[1], "/msg %s %s\n", target, msg);
         }
       }
+      else if(!strncmp(buf, "NICK ", 5))
+      {
+        char* nick=&buf[5];
+        if(nick[0]==':'){nick=&nick[1];}
+        dprintf(tc_in[1], "/nick %s\n", nick);
+      }
       else if(!strncmp(buf, "PING ", 5))
       {
         dprintf(sock, ":irchack PONG %s\n", &buf[5]);