$ 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, ¤tcolor, 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]);