char *growl_generate_authheader_alloc(const char*const password) { char* salt; char* salthash; char* keyhash; char* authheader = NULL; if (password) { salt = gen_salt_alloc(8); if (salt) { keyhash = gen_password_hash_alloc(password, salt); if (keyhash) { salthash = string_to_hex_alloc(salt, 8); if (salthash) { authheader = (char*)PhAllocateSafe(strlen(keyhash) + strlen(salthash) + 7); if (authheader) { sprintf(authheader, " MD5:%s.%s", keyhash, salthash); } PhFree(salthash); } PhFree(keyhash); } PhFree(salt); } } return authheader; }
char *get_icon_id( const char *const icon , size_t *size ) { size_t bytes_read; md5_context md5ctx; char md5tmp[20]; size_t iconsize = 0; char *iconid = NULL; uint8_t buffer[1024]; FILE *iconfile = fopen(icon, "rb"); if (iconfile) { fseek(iconfile, 0, SEEK_END); iconsize = ftell(iconfile); fseek(iconfile, 0, SEEK_SET); memset(md5tmp, 0, sizeof(md5tmp)); md5_starts(&md5ctx); while (!feof(iconfile)) { bytes_read = fread(buffer, 1, 1024, iconfile); if (bytes_read) md5_update(&md5ctx, buffer, bytes_read); } fseek(iconfile, 0, SEEK_SET); md5_finish(&md5ctx, md5tmp); iconid = string_to_hex_alloc(md5tmp, 16); fclose(iconfile); *size = iconsize; return iconid; } return NULL; }
char* gen_password_hash_alloc(const char* password, const char* salt) { md5_context md5ctx; char md5tmp[20]; char* md5digest; memset(md5tmp, 0, sizeof(md5tmp)); md5_starts(&md5ctx); md5_update(&md5ctx, (uint8_t*)password, (uint32_t)strlen(password)); md5_update(&md5ctx, (uint8_t*)salt, (uint32_t)strlen(salt)); md5_finish(&md5ctx, (uint8_t*)md5tmp); md5_starts(&md5ctx); md5_update(&md5ctx, (uint8_t*)md5tmp, 16); md5_finish(&md5ctx, (uint8_t*)md5tmp); md5digest = string_to_hex_alloc(md5tmp, 16); return md5digest; }
char* gen_password_hash_alloc(const char* password, const char* salt) { md5_state_t state; md5_byte_t md5tmp[20]; char* md5digest; memset(md5tmp, 0, sizeof(md5tmp)); md5_init(&state); md5_append(&state, (const md5_byte_t *)password, strlen(password)); md5_append(&state, (const md5_byte_t *)salt, strlen(salt)); md5_finish(&state, md5tmp); md5_init(&state); md5_append(&state, (const md5_byte_t *)md5tmp, 16); md5_finish(&state, md5tmp); md5digest = string_to_hex_alloc(md5tmp, 16); //fprintf(stderr, "digest: %s\n", md5digest); return md5digest; }
/* dmex: modified to use INVALID_SOCKET */ 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) { SOCKET sock = INVALID_SOCKET; char *authheader = growl_generate_authheader_alloc(password); char *iconid = NULL; FILE *iconfile = NULL; size_t iconsize; uint8_t buffer[1024]; growl_init(); sock = growl_tcp_open(server); if (sock == INVALID_SOCKET) goto leave; if (icon) { size_t bytes_read; md5_context md5ctx; char md5tmp[20]; iconfile = fopen(icon, "rb"); if (iconfile) { fseek(iconfile, 0, SEEK_END); iconsize = ftell(iconfile); fseek(iconfile, 0, SEEK_SET); memset(md5tmp, 0, sizeof(md5tmp)); md5_starts(&md5ctx); while (!feof(iconfile)) { bytes_read = fread(buffer, 1, 1024, iconfile); if (bytes_read) md5_update(&md5ctx, buffer, (uint32_t)bytes_read); } fseek(iconfile, 0, SEEK_SET); md5_finish(&md5ctx, md5tmp); iconid = string_to_hex_alloc(md5tmp, 16); } } growl_tcp_write(sock, "GNTP/1.0 NOTIFY NONE %s", authheader ? authheader : ""); growl_tcp_write(sock, "Application-Name: %s", appname); growl_tcp_write(sock, "Notification-Name: %s", notify); growl_tcp_write(sock, "Notification-Title: %s", title); growl_tcp_write(sock, "Notification-Text: %s", message); if(iconid) { growl_tcp_write(sock, "Notification-Icon: x-growl-resource://%s", iconid); } else if(icon) { growl_tcp_write(sock, "Notification-Icon: %s", icon ); } if (url) growl_tcp_write(sock, "Notification-Callback-Target: %s", url ); if (iconid) { growl_tcp_write(sock, "Identifier: %s", iconid); growl_tcp_write(sock, "Length: %d", iconsize); growl_tcp_write(sock, ""); while (!feof(iconfile)) { size_t bytes_read = fread(buffer, 1, 1024, iconfile); if (bytes_read) growl_tcp_write_raw(sock, buffer, (int)bytes_read); } growl_tcp_write(sock, "" ); } growl_tcp_write(sock, ""); while (1) { char* line = growl_tcp_read(sock); if (!line) { growl_tcp_close(sock); sock = INVALID_SOCKET; goto leave; } else { int len = (int)strlen(line); /* fprintf(stderr, "%s\n", line); */ if (strncmp(line, "GNTP/1.0 -ERROR", 15) == 0) { if (strncmp(line + 15, " NONE", 5) != 0) { fprintf(stderr, "failed to post notification\n"); PhFree(line); goto leave; } } PhFree(line); if (len == 0) break; } } growl_tcp_close(sock); sock = 0; leave: if (iconfile) fclose(iconfile); if (iconid) PhFree(iconid); if (authheader) PhFree(authheader); return (sock == 0) ? 0 : INVALID_SOCKET; }