COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
growl.c
Go to the documentation of this file.
1 #ifdef _WIN32
2 #include <windows.h>
3 #else
4 #include <arpa/inet.h>
5 #include <stdint.h>
6 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <time.h>
11 
12 #include "md5.h"
13 #include "tcp.h"
14 #include "growl.h"
15 
16 static const char hex_table[] = "0123456789ABCDEF";
17 static char* string_to_hex_alloc(const char* str, int len) {
18  int n, l;
19  char* tmp = (char*)malloc(len * 2 + 1);
20  memset(tmp, 0, len * 2 + 1);
21  for (l = 0, n = 0; l < len; l++) {
22  tmp[n++] = hex_table[(str[l] & 0xF0) >> 4];
23  tmp[n++] = hex_table[str[l] & 0x0F];
24  }
25  return tmp;
26 }
27 
28 int growl_init_ = 0;
29 
31 {
32  if( growl_init_ == 0)
33  {
34  #ifdef _WIN32
35  WSADATA wsaData;
36  if( WSAStartup( MAKEWORD( 2 , 0 ) , &wsaData) != 0 )
37  {
38  return -1;
39  }
40  #endif
41 
42  srand(time(NULL));
43  growl_init_ = 1;
44  }
45  return 1;
46 }
47 
48 
50 {
51  if( growl_init_ == 1 )
52  {
53  #ifdef _WIN32
54  WSACleanup();
55  #endif
56  }
57 }
58 
59 
60 char* gen_salt_alloc(int count) {
61  char* salt = (char*)malloc(count + 1);
62  int n;
63  for (n = 0; n < count; n++) salt[n] = (((int)rand()) % 255) + 1;
64  salt[n] = 0;
65  return salt;
66 }
67 
68 char* gen_password_hash_alloc(const char* password, const char* salt) {
69  md5_context md5ctx;
70  char md5tmp[20];
71  char* md5digest;
72 
73  memset(md5tmp, 0, sizeof(md5tmp));
74  md5_starts(&md5ctx);
75  md5_update(&md5ctx, (uint8_t*)password, strlen(password));
76  md5_update(&md5ctx, (uint8_t*)salt, strlen(salt));
77  md5_finish(&md5ctx, (uint8_t*)md5tmp);
78 
79  md5_starts(&md5ctx);
80  md5_update(&md5ctx, (uint8_t*)md5tmp, 16);
81  md5_finish(&md5ctx, (uint8_t*)md5tmp);
82  md5digest = string_to_hex_alloc(md5tmp, 16);
83 
84  return md5digest;
85 }
86 
87 char *growl_generate_authheader_alloc(const char*const password)
88 {
89  char* salt;
90  char* salthash;
91  char* keyhash;
92  char* authheader = NULL;
93 
94  if (password) {
95  salt = gen_salt_alloc(8);
96  keyhash = gen_password_hash_alloc(password, salt);
97  salthash = string_to_hex_alloc(salt, 8);
98  free(salt);
99  authheader = (char*)malloc(strlen(keyhash) + strlen(salthash) + 7);
100  sprintf(authheader, " MD5:%s.%s", keyhash, salthash);
101  free(salthash);
102  free(keyhash);
103  }
104 
105  return authheader;
106 }
107 
108 
109 int growl_tcp_register( const char *const server , const char *const appname , const char **const notifications , const int notifications_count ,
110  const char *const password, const char* const icon )
111 {
112  int sock = -1;
113  int i=0;
114  char *authheader;
115  char empty[0];
116  growl_init();
117  authheader = growl_generate_authheader_alloc(password);
118  sock = growl_tcp_open(server);
119  if (sock == -1) goto leave;
120 
121  growl_tcp_write(sock, "GNTP/1.0 REGISTER NONE %s", authheader ? authheader : "");
122  growl_tcp_write(sock, "Application-Name: %s", appname);
123  if(icon) growl_tcp_write(sock, "Application-Icon: %s", icon);
124  growl_tcp_write(sock, "Notifications-Count: %d", notifications_count);
125  growl_tcp_write(sock, "%s", empty);
126 
127  for(i=0;i<notifications_count;i++)
128  {
129  growl_tcp_write(sock, "Notification-Name: %s", notifications[i]);
130  growl_tcp_write(sock, "Notification-Display-Name: %s", notifications[i]);
131  growl_tcp_write(sock, "Notification-Enabled: True" );
132  if(icon) growl_tcp_write(sock, "Notification-Icon: %s", icon);
133  growl_tcp_write(sock, "%s", empty);
134  }
135  while (1) {
136  char* line = growl_tcp_read(sock);
137  int len = strlen(line);
138  /* fprintf(stderr, "%s\n", line); */
139  if (strncmp(line, "GNTP/1.0 -ERROR", 15) == 0) {
140  fprintf(stderr, "failed to register notification\n");
141  free(line);
142  goto leave;
143  }
144  free(line);
145  if (len == 0) break;
146  }
147  growl_tcp_close(sock);
148  sock = 0;
149 
150  leave:
151  if (authheader) free(authheader);
152 
153  return (sock == 0) ? 0 : -1;
154 }
155 
156 
157 int growl_tcp_notify( const char *const server,const char *const appname,const char *const notify,const char *const title, const char *const message ,
158  const char *const password, const char* const url, const char* const icon)
159 {
160  int sock = -1;
161 
162  char *authheader = growl_generate_authheader_alloc(password);
163  char empty[0];
164  growl_init();
165 
166  sock = growl_tcp_open(server);
167  if (sock == -1) goto leave;
168 
169  growl_tcp_write(sock, "GNTP/1.0 NOTIFY NONE %s", authheader ? authheader : "");
170  growl_tcp_write(sock, "Application-Name: %s", appname);
171  growl_tcp_write(sock, "Notification-Name: %s", notify);
172  growl_tcp_write(sock, "Notification-Title: %s", title);
173  growl_tcp_write(sock, "Notification-Text: %s", message);
174  if (icon) growl_tcp_write(sock, "Notification-Icon: %s", icon);
175  if (url) growl_tcp_write(sock, "Notification-Callback-Target: %s", url );
176 
177  growl_tcp_write(sock, "%s", empty);
178  while (1) {
179  char* line = growl_tcp_read(sock);
180  int len = strlen(line);
181  /* fprintf(stderr, "%s\n", line); */
182  if (strncmp(line, "GNTP/1.0 -ERROR", 15) == 0) {
183  fprintf(stderr, "failed to post notification\n");
184  free(line);
185  goto leave;
186  }
187  free(line);
188  if (len == 0) break;
189  }
190  growl_tcp_close(sock);
191  sock = 0;
192 
193 leave:
194  if (authheader) free(authheader);
195 
196  return (sock == 0) ? 0 : -1;
197 }
198 
199 
200 
201 int growl( const char *const server,const char *const appname,const char *const notify,const char *const title, const char *const message ,
202  const char *const icon , const char *const password , const char *url )
203 {
204  int rc = growl_tcp_register( server , appname , (const char **const)&notify , 1 , password, icon );
205  if( rc == 0 )
206  {
207  rc = growl_tcp_notify( server, appname, notify, title, message , password, url, icon );
208  }
209  return rc;
210 }
211 
212 
213 void growl_append_md5( unsigned char *const data , const int data_length , const char *const password )
214 {
215  md5_context md5ctx;
216  char md5tmp[20];
217 
218  memset(md5tmp, 0, sizeof(md5tmp));
219  md5_starts(&md5ctx);
220  md5_update(&md5ctx, (uint8_t*)data, data_length );
221  if(password != NULL)
222  {
223  md5_update(&md5ctx, (uint8_t*)password, strlen(password));
224  }
225  md5_finish(&md5ctx, (uint8_t*)md5tmp);
226 
227  memcpy( data + data_length , md5tmp , 16 );
228 }
229 
230 
231 int growl_udp_register( const char *const server , const char *const appname , const char **const notifications , const int notifications_count , const char *const password )
232 {
233  int register_header_length = 22+strlen(appname);
234  unsigned char *data;
235  int pointer = 0;
236  int rc = 0;
237  int i=0;
238 
239  uint8_t GROWL_PROTOCOL_VERSION = 1;
240  uint8_t GROWL_TYPE_REGISTRATION = 0;
241 
242  uint16_t appname_length = ntohs(strlen(appname));
243  uint8_t _notifications_count = notifications_count;
244  uint8_t default_notifications_count = notifications_count;
245  uint8_t j;
246 
247  growl_init();
248 
249  for(i=0;i<notifications_count;i++)
250  {
251  register_header_length += 3 + strlen(notifications[i]);
252  }
253  data = (unsigned char*)malloc(register_header_length);
254  memset( data , 0 , register_header_length );
255 
256 
257  pointer = 0;
258  memcpy( data + pointer , &GROWL_PROTOCOL_VERSION , 1 );
259  pointer++;
260  memcpy( data + pointer , &GROWL_TYPE_REGISTRATION , 1 );
261  pointer++;
262  memcpy( data + pointer , &appname_length , 2 );
263  pointer += 2;
264  memcpy( data + pointer , &_notifications_count , 1 );
265  pointer++;
266  memcpy( data + pointer, &default_notifications_count , 1 );
267  pointer++;
268  sprintf( (char*)data + pointer , "%s" , appname );
269  pointer += strlen(appname);
270 
271  for(i=0;i<notifications_count;i++)
272  {
273  uint16_t notify_length = ntohs(strlen(notifications[i]));
274  memcpy( data + pointer, &notify_length , 2 );
275  pointer +=2;
276  sprintf( (char*)data + pointer , "%s" , notifications[i] );
277  pointer += strlen(notifications[i]);
278  }
279 
280  for(j=0;j<notifications_count;j++)
281  {
282  memcpy( data + pointer , &j , 1 );
283  pointer++;
284  }
285 
286  growl_append_md5( data , pointer , password );
287  pointer += 16;
288 
289  rc = growl_tcp_datagram( server , data , pointer );
290  free(data);
291  return rc;
292 }
293 
294 
295 int growl_udp_notify( const char *const server,const char *const appname,const char *const notify,const char *const title, const char *const message ,
296  const char *const password )
297 {
298  int notify_header_length = 28 + strlen(appname)+strlen(notify)+strlen(message)+strlen(title);
299  unsigned char *data = (unsigned char*)malloc(notify_header_length);
300  int pointer = 0;
301  int rc = 0;
302 
303  uint8_t GROWL_PROTOCOL_VERSION = 1;
304  uint8_t GROWL_TYPE_NOTIFICATION = 1;
305 
306  uint16_t flags = ntohs(0);
307  uint16_t appname_length = ntohs(strlen(appname));
308  uint16_t notify_length = ntohs(strlen(notify));
309  uint16_t title_length = ntohs(strlen(title));
310  uint16_t message_length = ntohs(strlen(message));
311 
312  growl_init();
313  memset( data , 0 , notify_header_length );
314 
315  pointer = 0;
316  memcpy( data + pointer , &GROWL_PROTOCOL_VERSION , 1 );
317  pointer++;
318  memcpy( data + pointer , &GROWL_TYPE_NOTIFICATION , 1 );
319  pointer++;
320  memcpy( data + pointer , &flags , 2 );
321  pointer += 2;
322  memcpy( data + pointer , &notify_length , 2 );
323  pointer += 2;
324  memcpy( data + pointer , &title_length , 2 );
325  pointer += 2;
326  memcpy( data + pointer , &message_length , 2 );
327  pointer += 2;
328  memcpy( data + pointer , &appname_length , 2 );
329  pointer += 2;
330  strcpy( (char*)data + pointer , notify );
331  pointer += strlen(notify);
332  strcpy( (char*)data + pointer , title );
333  pointer += strlen(title);
334  strcpy( (char*)data + pointer , message );
335  pointer += strlen(message);
336  strcpy( (char*)data + pointer , appname );
337  pointer += strlen(appname);
338 
339 
340  growl_append_md5( data , pointer , password );
341  pointer += 16;
342 
343 
344  rc = growl_tcp_datagram( server , data , pointer );
345  free(data);
346  return rc;
347 }
348 
349 
350 int growl_udp( const char *const server,const char *const appname,const char *const notify,const char *const title, const char *const message ,
351  const char *const icon , const char *const password , const char *url )
352 {
353  int rc = growl_udp_register( server , appname , (const char **const)&notify , 1 , password );
354  if( rc == 0 )
355  {
356  rc = growl_udp_notify( server, appname, notify, title, message , password );
357  }
358  return rc;
359 }
360 
361 
362 #ifdef _WIN32
363 
364 void GrowlNotify(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
365  char* server = "127.0.0.1:23053";
366  char* password = NULL;
367  char* appname = "gntp-send";
368  char* notify = "gntp-send notify";
369  char* title = NULL;
370  char* message = NULL;
371  char* icon = NULL;
372  char* url = NULL;
373  char* first = strdup(lpszCmdLine);
374  char* ptr = first;
375  int rc;
376  WSADATA wsaData;
377  if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) return;
378  #define SKIP(x) while (*x && *x != ' ') x++; if (*x == ' ') *x++ = 0;
379  server = ptr; SKIP(ptr);
380  appname = ptr; SKIP(ptr);
381  notify = ptr; SKIP(ptr);
382  title = ptr; SKIP(ptr);
383  message = ptr; SKIP(ptr);
384  icon = ptr; SKIP(ptr);
385  url = ptr; SKIP(ptr);
386  rc = growl(server,appname,notify,title,message,icon,password,url);
387  WSACleanup();
388  free(ptr);
389 }
390 #endif
int growl_udp_register(const char *const server, const char *const appname, const char **const notifications, const int notifications_count, const char *const password)
Definition: growl.c:231
int growl_udp_notify(const char *const server, const char *const appname, const char *const notify, const char *const title, const char *const message, const char *const password)
Definition: growl.c:295
void md5_update(md5_context *ctx, const uint8_t *input, uint32_t length)
Definition: md5.c:140
int growl_init()
Definition: growl.c:30
unsigned short uint16_t
Definition: stdint.h:79
void char * growl_tcp_read(int sock)
Definition: tcp.c:45
char * gen_salt_alloc(int count)
Definition: growl.c:60
unsigned char uint8_t
Definition: stdint.h:78
tuple flags
Definition: coolfluid.py:7
int growl_udp(const char *const server, const char *const appname, const char *const notify, const char *const title, const char *const message, const char *const icon, const char *const password, const char *url)
Definition: growl.c:350
int growl_tcp_register(const char *const server, const char *const appname, const char **const notifications, const int notifications_count, const char *const password, const char *const icon)
Definition: growl.c:109
char * gen_password_hash_alloc(const char *password, const char *salt)
Definition: growl.c:68
void growl_tcp_close(int sock)
Definition: tcp.c:97
void growl_shutdown()
Definition: growl.c:49
void md5_starts(md5_context *ctx)
Definition: md5.c:8
char * growl_generate_authheader_alloc(const char *const password)
Definition: growl.c:87
void md5_finish(md5_context *ctx, uint8_t digest[16])
Definition: md5.c:181
int growl_init_
Definition: growl.c:28
int growl_tcp_notify(const char *const server, const char *const appname, const char *const notify, const char *const title, const char *const message, const char *const password, const char *const url, const char *const icon)
Definition: growl.c:157
void growl_tcp_write(int sock, const char *const format,...) __attribute__((format(printf
static const char hex_table[]
Definition: growl.c:16
int growl_tcp_open(const char *server)
Definition: tcp.c:64
static char * string_to_hex_alloc(const char *str, int len)
Definition: growl.c:17
int growl(const char *const server, const char *const appname, const char *const notify, const char *const title, const char *const message, const char *const icon, const char *const password, const char *url)
Definition: growl.c:201
void growl_append_md5(unsigned char *const data, const int data_length, const char *const password)
Definition: growl.c:213
Uint count(const RangeT &range)
Count the elements in a range.
int growl_tcp_datagram(const char *server, const unsigned char *data, const int data_length)
Definition: tcp.c:135
Send comments to:
COOLFluiD Web Admin