Add to git.
[monolith.git] / chat / message.c
1 /* Monolith message.
2  * - by Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: message.c,v 1.4 2003/02/22 12:56:26 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #ifdef HAVE_ASSERT_H
27 #include <assert.h>
28 #endif
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33
34 #ifdef HAVE_ALLOCA_H
35 #include <alloca.h>
36 #endif
37
38 #include <pool.h>
39 #include <pstring.h>
40 #include <pthr_iolib.h>
41
42 #include <monolith.h>
43 #include <ml_smarttext.h>
44
45 #include "message.h"
46
47 enum message_type {
48   type_posting, type_enter, type_leave, type_blank
49 };
50
51 struct message
52 {
53   enum message_type type;       /* Type of message. */
54   union {
55     struct {
56       int hh, mm;               /* Time of posting. */
57       const char *body;         /* Message body (turned to HTML). */
58       int authorid;             /* Author user ID (0 == anonymous). */
59       const char *original_ip;  /* IP address as a string. */
60     } posting;
61   } u;
62   const char *username;         /* Printable username (null == anonymous). */
63 };
64
65 message
66 new_message_posting (pool pool, int hh, int mm,
67                      int authorid, const char *username,
68                      const char *original_ip,
69                      const char *body)
70 {
71   message m = pmalloc (pool, sizeof *m);
72
73   m->type = type_posting;
74   m->u.posting.hh = hh;
75   m->u.posting.mm = mm;
76   m->u.posting.authorid = authorid;
77   m->u.posting.original_ip = pstrdup (pool, original_ip);
78   m->u.posting.body = ml_smarttext_to_html (pool, body);
79   m->username = username ? pstrdup (pool, username) : 0;
80
81   return m;
82 }
83
84 message
85 new_message_enter (pool pool, const char *username)
86 {
87   message m = pmalloc (pool, sizeof *m);
88
89   m->type = type_enter;
90   m->username = username ? pstrdup (pool, username) : 0;
91
92   return m;
93 }
94
95 message
96 new_message_leave (pool pool, const char *username)
97 {
98   message m = pmalloc (pool, sizeof *m);
99
100   m->type = type_leave;
101   m->username = username ? pstrdup (pool, username) : 0;
102
103   return m;
104 }
105
106 message
107 new_message_blank (pool pool)
108 {
109   message m = pmalloc (pool, sizeof *m);
110
111   m->type = type_blank;
112
113   return m;
114 }
115
116 static const char *
117 colour_for_user (int userid)
118 {
119   switch (userid & 7)
120     {
121     case 0: return "#990033";   /* Also used for anonymous users. */
122     case 1: return "#ff0066";
123     case 2: return "#cc00cc";
124     case 3: return "#6600cc";
125     case 4: return "#3333ff";
126     case 5: return "#003366";
127     case 6: return "#009999";
128     case 7: return "#ff9900";
129     }
130   /*NOTREACHED*/
131   return 0;
132 }
133
134 void
135 message_show (const message m, io_handle io)
136 {
137   const char *username;
138   const char *colour;
139   const char *anon = "anonymous";
140
141   switch (m->type)
142     {
143     case type_posting:
144       /* Construct the username. */
145       if (m->u.posting.authorid)
146         /* Ugh. We promise not to modify it! */
147         username = m->username;
148       else
149         {
150           int len = strlen (anon) + strlen (m->u.posting.original_ip) + 2;
151           char *u;
152
153           u = alloca (len);
154           snprintf (u, len, "%s@%s", anon, m->u.posting.original_ip);
155           username = u;
156         }
157
158       /* Pick a colour. */
159       colour = colour_for_user (m->u.posting.authorid);
160
161       /* Display it. */
162       /* XXX Escaping! */
163       io_fprintf (io,
164                   "<span class=\"ml_chat_time\">%02d:%02d</span> "
165                   "<span class=\"ml_chat_username\">&lt;%s&gt;</span> "
166                   "<span class=\"ml_chat_message\" "
167                   "style=\"color: %s\">%s</span><br>",
168                   m->u.posting.hh, m->u.posting.mm, username, colour,
169                   m->u.posting.body);
170       break;
171
172     case type_enter:
173       if (m->username)
174         {
175           /* XXX Escaping! */
176           io_fprintf (io,
177                       "<span class=\"ml_chat_enterleave\">"
178                       "<span class=\"ml_chat_username\">%s</span> "
179                       "has entered the room</span><br>",
180                       m->username);
181         }
182       else
183         {
184           io_fprintf (io,
185                       "<span class=\"ml_chat_enterleave\">"
186                       "an anonymous user has entered the room</span><br>");
187         }
188
189       break;
190
191     case type_leave:
192       if (m->username)
193         {
194           /* XXX Escaping! */
195           io_fprintf (io,
196                       "<span class=\"ml_chat_enterleave\">"
197                       "<span class=\"ml_chat_username\">%s</span> "
198                       "has left the room</span><br>",
199                       m->username);
200         }
201       else
202         {
203           io_fprintf (io,
204                       "<span class=\"ml_chat_enterleave\">"
205                       "an anonymous user has left the room</span><br>");
206         }
207
208       break;
209
210     case type_blank:
211       io_fputs (" ", io);
212
213       break;
214     }
215 }