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

    Version 0.2

diff --git a/ChangeLog b/ChangeLog
index d887e2f..acf024e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,181 +1,2 @@
-0.30:
-Adjusted the configure script for compatibility with shells that still interpret escaped characters in single-quotes (contributed by Jade)
-Added a /topic command to set the channel topic.
-tc_client-gtk: allow scrollbars around the cams, otherwise resizing the window to a smaller size will be blocked.
-tc_client-gtk: added optional notification sounds and a settings window to configure it.
-tc_client-gtk: added optional logging.
-tc_client-gtk: added a startup dialog instead of requiring commandline arguments.
-tc_client-gtk: display the color of our outgoing messages.
-tc_client-gtk: added an option to run a command for youtube videos being played.
-cursedchat: keep track of our own nickname and print that when we send a message instead of "You:" (contributed by Pamela)
-cursedchat: added timestamps for outgoing messages.
-0.29:
-Added testbuilds.sh to automatically try building the project with different configurations to verify that the latest changes did not break it in some cases.
-Check for endianness macros in the configure script and if they are missing/broken, test endianness and add our own macros.
-If getkey() returns null, print a descriptive message and exit (instead of segfaulting)
-Added optional code to record incoming RTMP packets, add -DRTMP_DEBUG=1 to CFLAGS to enable.
-Added compatibility hacks for apple systems (building onto android ones)
-Handle /help without sending it as a message.
-camviewer: create a new pipe for showing our own cam instead of mixing it in with tc_client's output.
-camviewer: remove associated cameras when a user leaves (in case there was no explicit message about ending the stream)
-camviewer: support older versions of libav which had parts of libavutil in libavcore instead.
-Forked camviewer into tc_client-gtk to keep camviewer as a simpler demo while tc_client-gtk develops into a more complete client interface.
-tc_client-gtk: added a menubar and moved the broadcasting option to there instead of as a button.
-tc_client-gtk: scale cams to fit/fill into the window.
-tc_client-gtk: added a text view for chat, an input field and a user list, switched to a glade file instead of building the GUI manually from code.
-modbot: added a !syncvid command to synchronize video position (or to see a video that was started while having youtube videos disabled in the flash client)
-0.28:
-Delete streams when they stop, to allow reusing stream IDs.
-Added a /camdown command.
-camviewer: worked around the cam streaming issue.
-camviewer: switched to libavresample instead of libswresample (when available)
-modbot: added a !modstats command to see how often there are moderators present.
-modbot: moved the help-text into an HTML document.
-modbot: added a -v/--verbose option to print/log all incoming messages.
-modbot: pass on error messages from youtube-dl when requesting a video fails.
-cursedchat: added history (up/down arrows)
-0.27:
-Added some more compatibility hacks for android.
-Added support for video broadcasting (adding /camup and /video <length> followed by the encoded data for each frame)
-crossbuild.sh: build ncurses and readline for the target platform.
-cursedchat: disable readline's match-listing, which does not work well with the curses interface.
-cursedchat: made tab completion work with nicknames.
-0.26:
-modbot: fixed a segfault when trying to skip more videos than what's in the queue.
-modbot: fixed a segfault when receiving a manual /mbc command but no video is playing.
-cursedchat: added PM buffers/windows which can be switched between with "/pm <name>", just "/pm" to return to the channel buffer.
-cursedchat: added /help output specific to cursedchat, in addition to tc_client's output.
-camviewer: added an experimental audio mixer.
-0.25:
-Handle short reads in the RTMP headers too.
-Added the option -c/--color <number> to pick color instead of getting a random color at startup (contributed by Pamela)
-cursedchat: use default colors (for background in particular)
-cursedchat: added scrolling.
-modbot: fixed singular form of 'videos' in !queue response.
-modbot: update 'requested' (for !requestedby) also when a video is played manually.
-camviewer: added basic mic code (mixing is still missing so it is disabled by default, to enable, configure with environment variable ENABLE_MIC set to 1)
-0.24:
-Fixed endianness of RTMP set-chunk-size handling.
-modbot: fixed a bug where '!wrongrequest' would claim no request was found when (and only when) the request was last in queue.
-modbot: added the options -d/--daemon and -l/--log plus better handling of -h/--help.
-modbot: moved and changed the note about '!approve entire queue' overuse to a note about making sure none of the videos were inappropriate in the "Queue approved" message.
-camviewer: fixed a bug introduced in 0.23 where audio data was handled improperly, resulting in audio/video data being missed.
-camviewer: ignore 0-byte audio/video packets.
-0.23:
-Added the moderator commands /mute and /push2talk (contributed by Jade)
-Set tc_client as a dependency of utils.
-Implemented RTMP message type 1 (set chunk size)
-Writing audio data the same way video data is written.
-camviewer: fixed a bug where joining a channel where no one is on cam resulted in trying to view the cam for "", leading to an empty GtkImage in the row of cams. 
-camviewer: added labels under each image with people's nicknames.
-Added a basic ncurses utility called cursedchat.
-modbot: for manual /mbc, remove the video from goodvids.
-modbot: fixed a bug that caused a segfault when using !badvid if nothing was playing.
-modbot: added a response for !wrongrequest without an argument when no request is found.
-modbot: renamed !whorequested to !requestedby for the sake of immature minds.
-0.22:
-Cleaned up media.c/h which I forgot to clean up before releasing 0.21.
-Detect when someone cams down.
-Added a /names command to list who is online.
-camviewer: fall back to GTK+2 if GTK+3 is not available.
-camviewer: show multiple cameras (cams to view are now picked up from who is on cam when joining and whenever someone cams up instead of from argv[1])
-modbot: list at most 5 not yet approved videos for !queue to avoid sending messages which are too large.
-modbot: fixed a bug where removing a non-approved video from queue using !wrongrequest and that video was the first in queue, the second video in queue wouldn't be played.
-modbot: added !whorequested to see who requested the currently playing video.
-0.21:
-Renamed streamids to chunkids to better match the specification.
-Added a /close command for mods to close cam/mic streams.
-Added /ban, /banlist and /forgive commands.
-Added a /opencam command to receive cam data, and the 'camviewer' utility to handle the cam data (depends on libavcodec/libswscale and gtk+ 3.x), mostly as a reference.
-Do not echo while entering account password at runtime.
-Announce when someone cams up, and list who is on cam when joining.
-modbot: added !wrongrequest to undo a request.
-modbot: allow entering account password at runtime and without echo.
-modbot: added !skip/!skip <number> to skip videos in the queue.
-irchack: translate between /userinfo and WHOIS.
-0.20:
-Fixed amf0 reading of numbers (type 0)
-Added support for sending format 0 RTMP packets (which include the msgid field)
-Handle "/userinfo $request", responding with the account name if logged in and otherwise "tc_client" (which is not a valid tinychat account name but the flash client will show it anyway)
-Added a /priv command, mostly for use by modbot.
-Improved the way RTMP payloads are read from the stream.
-modbot: when someone joins, send a /mbs (start video) command with the current position in the video, but only to that user.
-0.19:
-Got unicode characters working, as it turns out tinychat doesn't use ISO-8859-1 but UTF-16 (which shares character codes with ISO-8859-1 below 256)
-Enable keepalive on the TCP socket.
-irchack: end session upon bad reads from tc_client.
-modbot: handle playlist links properly (youtube-dl gives us a newline-separated list of IDs)
-modbot: added '!approve entire queue', mostly for playlists.
-modbot: allow searching for ID also in !badvid
-0.18:
-This release only affects modbot:
-Switched to using youtube-dl for getting IDs (including proper searching)
-Fixed and clarified the !help text.
-When a video is next to be played and has not been approved for 2 minutes, move the first approved video to the front instead of moving the first video to the back.
-Added '!approve next' which approves the first thing in queue that is not yet approved.
-Added !time to get the amount of time left for the current video (mostly for debugging)
-Handle /mbsk (seeking)
-0.17:
-irchack: translate tc_client's "No such nick" to IRC's 401 (No such nick/channel)
-modbot: mark manually started videos as playing.
-modbot: fixed a memory error in list_del()
-Added a configure script to better handle platform differences (primarily that some systems need to link to libiconv, for others it is provided by libc)
-crossbuild.sh: build libiconv if necessary.
-modbot: added more responses to !approve to make it less confusing.
-modbot: pass -- to youtube-dl before the ID to avoid issues when IDs start with -
-0.16:
-Get and print the channel topic (contributed by Jade)
-irchack: fork and keep accepting connections.
-irchack: translate IRC's "\x01ACTION stuff\x01" (/me) into "*stuff*" for tc_client.
-modbot: add a 100ms delay between the lines of !help to prevent throttling.
-modbot: handle manual /mbs and /mbc commands (remove from queue, mark as good for /mbs)
-Added a /help command to list commands handled by tc_client at runtime.
-irchack: use USER and PASS IRC commands to get the tinychat account to login as.
-0.15:
-Fixed a bug introduced with the new argument handling in 0.14
-Prompt for password if a username is given with -u/--user but no password (-p/--pass) is given.
-Turn account names lowercase to comply with tinychat's quirks.
-Handle networking being down at startup more graciously.
-Added modbot.c, a bot that deals with playing videos.
-0.14:
-Use iconv to deal with tinychat's ISO-8859-1 instead of the wcs functions.
-irchack: only listen on 127.0.0.1 (localhost)
-Added -u/--user and -p/--pass options to log into tinychat accounts.
-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)
-Handle new nicknames being in use when using /nick, and thus failing (contributed by Jade)
-0.11:
-Rewrote the RTMP code to read from the socket instead of from a buffer, this will prevent messages from being dropped when they are larger than the buffer.
-0.10:
-irchack: stay connected if joining a channel fails and tell the IRC client if a channel password is required.
-irchack: keep listening for connections and accept the next after a session ends.
-0.9:
-Added compatibility workarounds for android.
-Keep track of who is a moderator. (contributed by Jade)
-Added crossbuild.sh script to automatically cross-compile tc_client and curl (dependency) for the given host-triplet.
-0.8:
-irchack: convert tc_client's ANSI codes to IRC color codes.
-irchack: convert IRC color codes to '/color <number>' commands for tc_client.
-Made it possible to turn off/on colors being displayed with '/color off' and '/color on'
-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. (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.
-0.3:
-Handle 'joins', 'join', 'nick' and 'quit' messages from the server (contributed by Jade)
-Moved the AMF message writing functions into a separate source file.
-Added irchack.c, a simple application that acts as an IRC server mirroring a tinychat channel using tc_client.
 0.2:
 Added support for non-ascii characters (sent as ISO-8859-1 to/from the server)
diff --git a/Makefile b/Makefile
index 3e4096d..c2adc8d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.1
+VERSION=0.2
 CFLAGS=-g3 -Wall $(shell curl-config --cflags)
 LIBS=-g3 $(shell curl-config --libs)
 
@@ -9,4 +9,4 @@ clean:
  rm -f client.o amfparser.o rtmp.o numlist.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 amfparser.h rtmp.h numlist.h LICENSE README
+ tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfparser.h rtmp.h numlist.h LICENSE README ChangeLog
diff --git a/client.c b/client.c
index 451d275..0f95878 100644
--- a/client.c
+++ b/client.c
@@ -22,6 +22,7 @@
 #include <sys/socket.h>
 #include <netdb.h>
 #include <poll.h>
+#include <locale.h>
 #include <curl/curl.h>
 #include "rtmp.h"
 #include "amfparser.h"
@@ -250,6 +251,7 @@ char* getkey(char* id, char* channel)
 
 int main(int argc, char** argv)
 {
+  setlocale(LC_ALL, "");
   if(argc<3)
    {
     printf("Usage: %s <roomname> <nickname> [password]\n", argv[0]);
@@ -404,7 +406,10 @@ int main(int argc, char** argv)
       len=read(0, buf, 2047);
       while(len>0 && (buf[len-1]=='\n'||buf[len-1]=='\r')){--len;}
       buf[len]=0;
-      char* msg=tonumlist((char*)buf);
+      len=mbstowcs(0, (char*)buf, 0);
+      wchar_t wcsbuf[len+1];
+      mbstowcs(wcsbuf, (char*)buf, len+1);
+      char* msg=tonumlist(wcsbuf);
       amfinit(&amf);
       amfstring(&amf, "privmsg");
       amfnum(&amf, 0);
@@ -467,11 +472,11 @@ int main(int argc, char** argv)
       // Items for privmsg: 0=cmd, 2=channel, 3=msg, 4=color/lang, 5=nick
       if(amfin->itemcount>0 && amfin->items[0].type==AMF_STRING && amf_comparestrings_c(&amfin->items[0].string, "privmsg") && amfin->items[3].type==AMF_STRING && amfin->items[5].type==AMF_STRING)
       {
-        char* msg=fromnumlist(amfin->items[3].string.string);
+        wchar_t* msg=fromnumlist(amfin->items[3].string.string);
         // Timestamps, e.g. "[hh:mm] name: message"
         time_t timestamp=time(0);
         struct tm* t=localtime(&timestamp);
-        printf("[%02i:%02i] %s: %s\n", t->tm_hour, t->tm_min, amfin->items[5].string.string, msg);
+        printf("[%02i:%02i] %s: %ls\n", t->tm_hour, t->tm_min, amfin->items[5].string.string, msg);
         free(msg);
       }
       amf_free(amfin);
diff --git a/numlist.c b/numlist.c
index d28c5f6..b1806a2 100644
--- a/numlist.c
+++ b/numlist.c
@@ -17,11 +17,13 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <wchar.h>
+#include <locale.h>
 #include "numlist.h"
 
 // Functions for converting to/from the comma-separated decimal character code format that tinychat uses for chat messages, e.g. "97,98,99" = "abc"
 
-char* fromnumlist(char* in)
+wchar_t* fromnumlist(char* in)
 {
   int len=1;
   char* x=in;
@@ -30,7 +32,7 @@ char* fromnumlist(char* in)
     ++len;
     x=&x[1];
   }
-  char* string=malloc(len+1);
+  unsigned char string[len+1];
   int i;
   for(i=0; i<len; ++i)
   {
@@ -39,11 +41,22 @@ char* fromnumlist(char* in)
     in=&in[1];
   }
   string[len]=0;
-  return string;
+  wchar_t* wstring=malloc(sizeof(wchar_t)*(len+1));
+  setlocale(LC_ALL, "en_US.ISO-8859-1");
+  mbstowcs(wstring, (char*)string, len);
+  wstring[len]=0;
+  setlocale(LC_ALL, "");
+  return wstring;
 }
 
-char* tonumlist(const char* in)
+char* tonumlist(const wchar_t* in_x)
 {
+  int len=wcslen(in_x);
+  char in[len+1];
+  setlocale(LC_ALL, "en_US.ISO-8859-1");
+  wcstombs(in, in_x, len);
+  in[len]=0;
+  setlocale(LC_ALL, "");
   char* out=malloc(strlen(in)*strlen("255,"));
   out[0]=0;
   char* x=out;
diff --git a/numlist.h b/numlist.h
index c76aece..115206e 100644
--- a/numlist.h
+++ b/numlist.h
@@ -14,5 +14,5 @@
     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 char* fromnumlist(char* in);
-extern char* tonumlist(const char* in);
+extern wchar_t* fromnumlist(char* in);
+extern char* tonumlist(const wchar_t* in);