$ git clone https://tcclient.ion.nu/tc_client.git
commit d42b2a02fb1f450d95325763b410dd1059f2e15e
Author: Alicia <...>
Date:   Tue Apr 7 06:49:01 2015 +0200

    Version 0.13

diff --git a/ChangeLog b/ChangeLog
index f2b31d1..166407b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+0.13:
+Check the validity of nicknames before switching.
+Roll our own endianness conversion functions since the ones provided by libc are not standardized.
 0.12:
 Wrote a sender for the RTMP code and changed the AMF0 writer to use it, plus working directly with the rtmp struct instead of an intermediate amfmsg struct.
 Added handling of moderators turning into regular users, or 'deop' (contributed by Jade)
diff --git a/Makefile b/Makefile
index a96e224..2c4e561 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
-VERSION=0.12
+VERSION=0.13
 CFLAGS=-g3 -Wall $(shell curl-config --cflags)
 LIBS=-g3 $(shell curl-config --libs)
 
-tc_client: client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o
+tc_client: client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o endian.o
  $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
 
 clean:
- rm -f client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o tc_client
+ rm -f client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o endian.o tc_client
 
 tarball:
- tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfwriter.c idlist.c colors.c amfparser.h rtmp.h numlist.h amfwriter.h idlist.h colors.h LICENSE README ChangeLog crossbuild.sh irchack.c
+ tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfwriter.c idlist.c colors.c endian.c amfparser.h rtmp.h numlist.h amfwriter.h idlist.h colors.h endian.h LICENSE README ChangeLog crossbuild.sh irchack.c
diff --git a/amfparser.c b/amfparser.c
index eadd1f6..3e0cf1b 100644
--- a/amfparser.c
+++ b/amfparser.c
@@ -16,8 +16,8 @@
 */
 #include <string.h>
 #include <stdlib.h>
-#include <endian.h>
 #include <stdio.h> // For debugging
+#include "endian.h"
 #include "amfparser.h"
 
 char amf_comparestrings_c(struct amfstring* a, const char* b)
@@ -71,7 +71,7 @@ struct amf* amf_parse(const unsigned char* buf, int len)
       obj=&amf->items[amf->itemcount-1].object;
       // TODO: recurse into unfinished member-objects (unimportant, I haven't seen any objects within objects so far)
       // Add member and set name
-      i=be16toh(*(short*)buf);
+      i=be16(*(short*)buf);
       buf=&buf[sizeof(short)];
       if(&buf[i]>=end){printf("Warning: skipping object item with name exceeding RTMP size (0x%x)\n", i);}
       if(&buf[i]<end && buf[i]!=9) // 9=end-of-object
@@ -115,7 +115,7 @@ struct amf* amf_parse(const unsigned char* buf, int len)
         item=&obj->members[obj->membercount-1].value;
       else
         item=amf_newitem(amf);
-      i=be16toh(*(short*)buf);
+      i=be16(*(short*)buf);
       buf=&buf[sizeof(short)];
       item->type=AMF_STRING;
       item->string.length=i;
diff --git a/amfwriter.c b/amfwriter.c
index dd51863..97876ec 100644
--- a/amfwriter.c
+++ b/amfwriter.c
@@ -18,7 +18,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <endian.h>
+#include "endian.h"
 #include "rtmp.h"
 #include "amfwriter.h"
 
@@ -59,7 +59,7 @@ void amfstring(struct rtmp* msg, const char* string)
   unsigned char* type=msg->buf+offset;
   type[0]='\x02';
   uint16_t* strlength=(uint16_t*)(msg->buf+offset+1);
-  *strlength=htobe16(len);
+  *strlength=be16(len);
   memcpy(msg->buf+offset+3, string, len);
 }
 
@@ -79,7 +79,7 @@ void amfobjitem(struct rtmp* msg, char* name)
   msg->length+=2+len;
   msg->buf=realloc(msg->buf, msg->length);
   uint16_t* strlength=(uint16_t*)(msg->buf+offset);
-  *strlength=htobe16(len);
+  *strlength=be16(len);
   memcpy(msg->buf+offset+2, name, len);
 }
 
diff --git a/client.c b/client.c
index c0fb10c..a1ae3da 100644
--- a/client.c
+++ b/client.c
@@ -41,19 +41,6 @@ struct writebuf
 
 char showcolor=1;
 
-unsigned int flip(unsigned int bits, int bytecount)
-{
-  unsigned int ret=0;
-  unsigned char* bytes=(unsigned char*)&bits;
-  unsigned char* retb=(unsigned char*)&ret;
-  int i;
-  for(i=0; i<bytecount; ++i)
-  {
-    retb[i]=bytes[bytecount-1-i];
-  }
-  return ret;
-}
-
 void b_read(int sock, void* buf, size_t len)
 {
   while(len>0)
@@ -157,6 +144,16 @@ char* timestamp()
   return timestampbuf;
 }
 
+char checknick(const char* nick) // Returns zero if the nick is valid, otherwise returning the character that failed the check
+{
+  unsigned int i;
+  for(i=0; nick[i]; ++i)
+  {
+    if(!strchr("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-^[]{}`\\|", nick[i])){return nick[i];}
+  }
+  return 0;
+}
+
 int main(int argc, char** argv)
 {
   setlocale(LC_ALL, "");
@@ -165,6 +162,12 @@ int main(int argc, char** argv)
     printf("Usage: %s <channelname> <nickname> [password]\n", argv[0]);
     return 1;
   }
+  char badchar;
+  if((badchar=checknick(argv[2])))
+  {
+    printf("'%c' is not allowed in nicknames.\n", badchar);
+    return 1;
+  }
   char* channel=argv[1];
   char* nickname=strdup(argv[2]);
   char* password=(argc>3?argv[3]:0);
@@ -299,6 +302,11 @@ int main(int argc, char** argv)
         }
         else if(!strncmp((char*)buf, "/nick ", 6))
         {
+          if((badchar=checknick((char*)&buf[6])))
+          {
+            printf("'%c' is not allowed in nicknames.\n", badchar);
+            continue;
+          }
           amfinit(&amf, 3);
           amfstring(&amf, "nick");
           amfnum(&amf, 0);
diff --git a/endian.c b/endian.c
index 17f9a2c..c327ab4 100644
--- a/endian.c
+++ b/endian.c
@@ -16,22 +16,6 @@
 */
 #include "endian.h"
 
-unsigned long long be64(unsigned long long in)
-{
-#if(__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__)
-  return ((in&0xff)<<56) |
-         ((in&0xff00)<<40) |
-         ((in&0xff0000)<<24) |
-         ((in&0xff000000)<<8) |
-         ((in&0xff00000000)>>8) |
-         ((in&0xff0000000000)>>24) |
-         ((in&0xff000000000000)>>40) |
-         ((in&0xff00000000000000)>>56);
-#else
-  return in;
-#endif
-}
-
 unsigned long be32(unsigned long in)
 {
 #if(__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__)
diff --git a/endian.h b/endian.h
index 1f87c60..790416d 100644
--- a/endian.h
+++ b/endian.h
@@ -14,7 +14,6 @@
     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-extern unsigned long long be64(unsigned long long in);
 extern unsigned long be32(unsigned long in);
 extern unsigned long le32(unsigned long in);
 extern unsigned short be16(unsigned short in);
diff --git a/rtmp.c b/rtmp.c
index 7ae7022..34261ee 100644
--- a/rtmp.c
+++ b/rtmp.c
@@ -18,7 +18,7 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
-#include <endian.h>
+#include "endian.h"
 #include "rtmp.h"
 
 char rtmp_get(int sock, struct rtmp* rtmp)
@@ -47,7 +47,7 @@ char rtmp_get(int sock, struct rtmp* rtmp)
       // Length
       x=0;
       read(sock, ((void*)&x)+1, 3);
-      length=be32toh(x);
+      length=be32(x);
       // Type
       read(sock, &type, sizeof(type));
       if(fmt<1)
@@ -62,7 +62,7 @@ char rtmp_get(int sock, struct rtmp* rtmp)
   if(timestamp==0xffffff)
   {
     read(sock, &x, sizeof(x));
-    timestamp=be32toh(x);
+    timestamp=be32(x);
   }
 
   rtmp->type=type;
@@ -93,7 +93,7 @@ void rtmp_send(int sock, struct rtmp* rtmp)
       unsigned char streamid=rtmp->streamid-64;
       write(sock, &streamid, sizeof(streamid));
     }else{
-      unsigned short streamid=htole16(rtmp->streamid-64);
+      unsigned short streamid=le16(rtmp->streamid-64);
       write(sock, &streamid, sizeof(streamid));
     }
   }
@@ -101,7 +101,7 @@ void rtmp_send(int sock, struct rtmp* rtmp)
   // Timestamp
   write(sock, &x, 3); // Time is irrelevant
   // Length
-  x=htobe32(rtmp->length);
+  x=be32(rtmp->length);
   write(sock, ((void*)&x)+1, 3);
   // Type
   write(sock, &rtmp->type, sizeof(rtmp->type));