go my file uploader
This commit is contained in:
26
plugins/ExtendedNotifications/gntp-send/LICENSE.txt
Normal file
26
plugins/ExtendedNotifications/gntp-send/LICENSE.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2009-2010 Yasuhiro Matsumoto
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
544
plugins/ExtendedNotifications/gntp-send/growl.c
Normal file
544
plugins/ExtendedNotifications/gntp-send/growl.c
Normal file
@@ -0,0 +1,544 @@
|
||||
#define _CRT_RAND_S
|
||||
#include <phdk.h>
|
||||
#include <winsock2.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "md5.h"
|
||||
#include "tcp.h"
|
||||
#include "growl.h"
|
||||
|
||||
static const char hex_table[] = "0123456789ABCDEF";
|
||||
static char* string_to_hex_alloc(const char* str, int len) {
|
||||
int n, l;
|
||||
char* tmp = (char*)PhAllocateSafe(len * 2 + 1);
|
||||
if (tmp) {
|
||||
memset(tmp, 0, len * 2 + 1);
|
||||
for (l = 0, n = 0; l < len; l++) {
|
||||
tmp[n++] = hex_table[(str[l] & 0xF0) >> 4];
|
||||
tmp[n++] = hex_table[str[l] & 0x0F];
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int growl_init_ = 0;
|
||||
|
||||
/* dmex: modified to use latest Winsock version */
|
||||
int growl_init()
|
||||
{
|
||||
if (growl_init_ == 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(WINSOCK_VERSION, &wsaData) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
growl_init_ = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void growl_shutdown()
|
||||
{
|
||||
if (growl_init_ == 1)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* dmex: modified to use a version of rand with security enhancements */
|
||||
char* gen_salt_alloc(int count)
|
||||
{
|
||||
char* salt = (char*)PhAllocateSafe(count + 1);
|
||||
|
||||
if (salt)
|
||||
{
|
||||
int n;
|
||||
int randSeed = 0;
|
||||
|
||||
rand_s(&randSeed);
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
salt[n] = (randSeed % 255) + 1;
|
||||
|
||||
salt[n] = 0;
|
||||
}
|
||||
|
||||
return salt;
|
||||
}
|
||||
|
||||
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 *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;
|
||||
}
|
||||
|
||||
/* dmex: modified to use INVALID_SOCKET */
|
||||
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 )
|
||||
{
|
||||
SOCKET sock = INVALID_SOCKET;
|
||||
int i=0;
|
||||
char *authheader;
|
||||
char *iconid = NULL;
|
||||
FILE *iconfile = NULL;
|
||||
size_t iconsize;
|
||||
uint8_t buffer[1024];
|
||||
|
||||
growl_init();
|
||||
authheader = growl_generate_authheader_alloc(password);
|
||||
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 REGISTER NONE %s", authheader ? authheader : "");
|
||||
growl_tcp_write(sock, "Application-Name: %s", appname);
|
||||
if(iconid)
|
||||
{
|
||||
growl_tcp_write(sock, "Application-Icon: x-growl-resource://%s", iconid);
|
||||
}
|
||||
else if(icon)
|
||||
{
|
||||
growl_tcp_write(sock, "Application-Icon: %s", icon );
|
||||
}
|
||||
growl_tcp_write(sock, "Notifications-Count: %d", notifications_count);
|
||||
growl_tcp_write(sock, "" );
|
||||
|
||||
for(i=0;i<notifications_count;i++)
|
||||
{
|
||||
growl_tcp_write(sock, "Notification-Name: %s", notifications[i]);
|
||||
growl_tcp_write(sock, "Notification-Display-Name: %s", notifications[i]);
|
||||
growl_tcp_write(sock, "Notification-Enabled: True" );
|
||||
if(iconid)
|
||||
{
|
||||
growl_tcp_write(sock, "Notification-Icon: x-growl-resource://%s", iconid);
|
||||
}
|
||||
else if(icon)
|
||||
{
|
||||
growl_tcp_write(sock, "Notification-Icon: %s", icon );
|
||||
}
|
||||
growl_tcp_write(sock, "" );
|
||||
}
|
||||
|
||||
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 register 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
int rc = growl_tcp_register( server , appname , (const char **const)¬ify , 1 , password, icon );
|
||||
if( rc == 0 )
|
||||
{
|
||||
rc = growl_tcp_notify( server, appname, notify, title, message , password, url, icon );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void growl_append_md5( unsigned char *const data , const int data_length , const char *const password )
|
||||
{
|
||||
md5_context md5ctx;
|
||||
char md5tmp[20];
|
||||
|
||||
memset(md5tmp, 0, sizeof(md5tmp));
|
||||
md5_starts(&md5ctx);
|
||||
md5_update(&md5ctx, (uint8_t*)data, data_length );
|
||||
if(password != NULL)
|
||||
{
|
||||
md5_update(&md5ctx, (uint8_t*)password, (uint32_t)strlen(password));
|
||||
}
|
||||
md5_finish(&md5ctx, (uint8_t*)md5tmp);
|
||||
|
||||
memcpy( data + data_length , md5tmp , 16 );
|
||||
}
|
||||
|
||||
|
||||
int growl_udp_register( const char *const server , const char *const appname , const char **const notifications , const int notifications_count , const char *const password )
|
||||
{
|
||||
int register_header_length = 22+(int)strlen(appname);
|
||||
unsigned char *data;
|
||||
int pointer = 0;
|
||||
int rc = 0;
|
||||
int i=0;
|
||||
|
||||
uint8_t GROWL_PROTOCOL_VERSION = 1;
|
||||
uint8_t GROWL_TYPE_REGISTRATION = 0;
|
||||
|
||||
uint16_t appname_length = ntohs((u_short)strlen(appname));
|
||||
uint8_t _notifications_count = notifications_count;
|
||||
uint8_t default_notifications_count = notifications_count;
|
||||
uint8_t j;
|
||||
|
||||
growl_init();
|
||||
|
||||
for(i=0;i<notifications_count;i++)
|
||||
{
|
||||
register_header_length += 3 + (int)strlen(notifications[i]);
|
||||
}
|
||||
data = (unsigned char*)PhAllocateSafe(register_header_length);
|
||||
if (!data) return -1;
|
||||
memset( data , 0 , register_header_length );
|
||||
|
||||
|
||||
pointer = 0;
|
||||
memcpy( data + pointer , &GROWL_PROTOCOL_VERSION , 1 );
|
||||
pointer++;
|
||||
memcpy( data + pointer , &GROWL_TYPE_REGISTRATION , 1 );
|
||||
pointer++;
|
||||
memcpy( data + pointer , &appname_length , 2 );
|
||||
pointer += 2;
|
||||
memcpy( data + pointer , &_notifications_count , 1 );
|
||||
pointer++;
|
||||
memcpy( data + pointer, &default_notifications_count , 1 );
|
||||
pointer++;
|
||||
sprintf( (char*)data + pointer , "%s" , appname );
|
||||
pointer += (int)strlen(appname);
|
||||
|
||||
for(i=0;i<notifications_count;i++)
|
||||
{
|
||||
uint16_t notify_length = ntohs((u_short)strlen(notifications[i]));
|
||||
memcpy( data + pointer, ¬ify_length , 2 );
|
||||
pointer +=2;
|
||||
sprintf( (char*)data + pointer , "%s" , notifications[i] );
|
||||
pointer += (int)strlen(notifications[i]);
|
||||
}
|
||||
|
||||
for(j=0;j<notifications_count;j++)
|
||||
{
|
||||
memcpy( data + pointer , &j , 1 );
|
||||
pointer++;
|
||||
}
|
||||
|
||||
growl_append_md5( data , pointer , password );
|
||||
pointer += 16;
|
||||
|
||||
rc = growl_tcp_datagram( server , data , pointer );
|
||||
PhFree(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
int notify_header_length = 28 + (int)(strlen(appname)+strlen(notify)+strlen(message)+strlen(title));
|
||||
unsigned char *data = (unsigned char*)PhAllocateSafe(notify_header_length);
|
||||
int pointer = 0;
|
||||
int rc = 0;
|
||||
|
||||
uint8_t GROWL_PROTOCOL_VERSION = 1;
|
||||
uint8_t GROWL_TYPE_NOTIFICATION = 1;
|
||||
|
||||
uint16_t flags = ntohs(0);
|
||||
uint16_t appname_length = ntohs((u_short)strlen(appname));
|
||||
uint16_t notify_length = ntohs((u_short)strlen(notify));
|
||||
uint16_t title_length = ntohs((u_short)strlen(title));
|
||||
uint16_t message_length = ntohs((u_short)strlen(message));
|
||||
|
||||
if (!data) return -1;
|
||||
|
||||
growl_init();
|
||||
memset( data , 0 , notify_header_length );
|
||||
|
||||
pointer = 0;
|
||||
memcpy( data + pointer , &GROWL_PROTOCOL_VERSION , 1 );
|
||||
pointer++;
|
||||
memcpy( data + pointer , &GROWL_TYPE_NOTIFICATION , 1 );
|
||||
pointer++;
|
||||
memcpy( data + pointer , &flags , 2 );
|
||||
pointer += 2;
|
||||
memcpy( data + pointer , ¬ify_length , 2 );
|
||||
pointer += 2;
|
||||
memcpy( data + pointer , &title_length , 2 );
|
||||
pointer += 2;
|
||||
memcpy( data + pointer , &message_length , 2 );
|
||||
pointer += 2;
|
||||
memcpy( data + pointer , &appname_length , 2 );
|
||||
pointer += 2;
|
||||
strcpy( (char*)data + pointer , notify );
|
||||
pointer += (int)strlen(notify);
|
||||
strcpy( (char*)data + pointer , title );
|
||||
pointer += (int)strlen(title);
|
||||
strcpy( (char*)data + pointer , message );
|
||||
pointer += (int)strlen(message);
|
||||
strcpy( (char*)data + pointer , appname );
|
||||
pointer += (int)strlen(appname);
|
||||
|
||||
|
||||
growl_append_md5( data , pointer , password );
|
||||
pointer += 16;
|
||||
|
||||
|
||||
rc = growl_tcp_datagram( server , data , pointer );
|
||||
PhFree(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
int rc = growl_udp_register( server , appname , (const char **const)¬ify , 1 , password );
|
||||
if( rc == 0 )
|
||||
{
|
||||
rc = growl_udp_notify( server, appname, notify, title, message , password );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
char *gntp_send_license_text =
|
||||
"[The \"BSD licence\"]\r\n"
|
||||
"Copyright (c) 2009-2010 Yasuhiro Matsumoto\r\n"
|
||||
"All rights reserved.\r\n"
|
||||
"\r\n"
|
||||
"Redistribution and use in source and binary forms, with or without\r\n"
|
||||
"modification, are permitted provided that the following conditions\r\n"
|
||||
"are met:\r\n"
|
||||
"\r\n"
|
||||
" 1. Redistributions of source code must retain the above copyright\r\n"
|
||||
" notice, this list of conditions and the following disclaimer.\r\n"
|
||||
" 2. Redistributions in binary form must reproduce the above copyright\r\n"
|
||||
" notice, this list of conditions and the following disclaimer in the\r\n"
|
||||
" documentation and/or other materials provided with the distribution.\r\n"
|
||||
" 3. The name of the author may not be used to endorse or promote products\r\n"
|
||||
" derived from this software without specific prior written permission.\r\n"
|
||||
"\r\n"
|
||||
"THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r\n"
|
||||
"IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r\n"
|
||||
"OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r\n"
|
||||
"IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r\n"
|
||||
"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r\n"
|
||||
"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r\n"
|
||||
"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r\n"
|
||||
"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r\n"
|
||||
"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r\n"
|
||||
"THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n"
|
||||
;
|
||||
33
plugins/ExtendedNotifications/gntp-send/growl.h
Normal file
33
plugins/ExtendedNotifications/gntp-send/growl.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _GROWL_H_
|
||||
#define _GROWL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
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 );
|
||||
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 );
|
||||
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 );
|
||||
|
||||
|
||||
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 );
|
||||
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 );
|
||||
int growl_udp_register( const char *const server , const char *const appname , const char **const notifications , const int notifications_count , const char *const password );
|
||||
|
||||
|
||||
int growl_init(void);
|
||||
void growl_shutdown(void);
|
||||
|
||||
extern char *gntp_send_license_text;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _GROWL_H_ */
|
||||
26
plugins/ExtendedNotifications/gntp-send/md5.h
Normal file
26
plugins/ExtendedNotifications/gntp-send/md5.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _MD5_H_
|
||||
#define _MD5_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
PH_HASH_CONTEXT hc;
|
||||
} md5_context;
|
||||
|
||||
__forceinline void md5_starts(md5_context *ctx)
|
||||
{
|
||||
PhInitializeHash(&ctx->hc, Md5HashAlgorithm);
|
||||
}
|
||||
|
||||
__forceinline void md5_update(md5_context *ctx, const uint8_t *input, uint32_t length)
|
||||
{
|
||||
PhUpdateHash(&ctx->hc, (PVOID)input, length);
|
||||
}
|
||||
|
||||
__forceinline void md5_finish(md5_context *ctx, uint8_t digest[16])
|
||||
{
|
||||
if (!PhFinalHash(&ctx->hc, digest, 16, NULL))
|
||||
PhRaiseStatus(STATUS_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
#endif /* _MD5_H_ */
|
||||
185
plugins/ExtendedNotifications/gntp-send/tcp.c
Normal file
185
plugins/ExtendedNotifications/gntp-send/tcp.c
Normal file
@@ -0,0 +1,185 @@
|
||||
#include <phdk.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "tcp.h"
|
||||
|
||||
int growl_tcp_parse_hostname( const char *const server , int default_port , struct sockaddr_in *const sockaddr );
|
||||
|
||||
void growl_tcp_write_raw( SOCKET sock, const unsigned char * data, const int data_length )
|
||||
{
|
||||
send(sock, data, data_length, 0);
|
||||
}
|
||||
|
||||
void growl_tcp_write( SOCKET sock , const char *const format , ... )
|
||||
{
|
||||
int length;
|
||||
char *output;
|
||||
char *stop;
|
||||
|
||||
va_list ap;
|
||||
|
||||
va_start( ap , format );
|
||||
length = vsnprintf( NULL , 0 , format , ap );
|
||||
va_end(ap);
|
||||
|
||||
va_start(ap,format);
|
||||
output = (char*)PhAllocateSafe(length+1);
|
||||
if (!output) {
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
vsnprintf( output , length+1 , format , ap );
|
||||
va_end(ap);
|
||||
|
||||
while ((stop = strstr(output, "\r\n"))) strcpy(stop, stop + 1);
|
||||
|
||||
send( sock , output , length , 0 );
|
||||
send( sock , "\r\n" , 2 , 0 );
|
||||
|
||||
PhFree(output);
|
||||
}
|
||||
|
||||
char *growl_tcp_read(SOCKET sock) {
|
||||
const int growsize = 80;
|
||||
char c = 0;
|
||||
char* line = (char*) PhAllocateSafe(growsize);
|
||||
if (line) {
|
||||
int len = growsize, pos = 0;
|
||||
char* newline;
|
||||
while (line) {
|
||||
if (recv(sock, &c, 1, 0) <= 0) break;
|
||||
if (c == '\r') continue;
|
||||
if (c == '\n') break;
|
||||
line[pos++] = c;
|
||||
if (pos >= len) {
|
||||
len += growsize;
|
||||
newline = (char*) realloc(line, len);
|
||||
if (!newline) {
|
||||
PhFree(line);
|
||||
return NULL;
|
||||
}
|
||||
line = newline;
|
||||
}
|
||||
}
|
||||
line[pos] = 0;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/* dmex: modified to use INVALID_SOCKET and SOCKET_ERROR */
|
||||
SOCKET growl_tcp_open(const char* server) {
|
||||
SOCKET sock = INVALID_SOCKET;
|
||||
#ifdef _WIN32
|
||||
char on;
|
||||
#else
|
||||
int on;
|
||||
#endif
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
if( growl_tcp_parse_hostname( server , 23053 , &serv_addr ) == -1 ) {
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
|
||||
perror("create socket");
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
|
||||
perror("connect");
|
||||
closesocket(sock); // dmex: fixed handle leaking on error
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
|
||||
perror("setsockopt");
|
||||
closesocket(sock); // dmex: fixed handle leaking on error
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* dmex: modified to use INVALID_SOCKET */
|
||||
void growl_tcp_close(SOCKET sock) {
|
||||
#ifdef _WIN32
|
||||
if (sock != INVALID_SOCKET) closesocket(sock);
|
||||
#else
|
||||
if (sock > 0) close(sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
int growl_tcp_parse_hostname( const char *const server , int default_port , struct sockaddr_in *const sockaddr )
|
||||
{
|
||||
char *hostname = PhDuplicateBytesZSafe((PSTR)server);
|
||||
char *port = strchr( hostname, ':' );
|
||||
struct hostent* host_ent;
|
||||
if( port != NULL )
|
||||
{
|
||||
*port = '\0';
|
||||
port++;
|
||||
default_port = atoi(port);
|
||||
}
|
||||
|
||||
host_ent = gethostbyname(hostname);
|
||||
if( host_ent == NULL )
|
||||
{
|
||||
perror("gethostbyname");
|
||||
PhFree(hostname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// dmex: fixed wrong sizeof argument
|
||||
memset( sockaddr , 0 , sizeof(struct sockaddr_in) );
|
||||
sockaddr->sin_family = AF_INET;
|
||||
memcpy( &sockaddr->sin_addr , host_ent->h_addr , host_ent->h_length );
|
||||
sockaddr->sin_port = htons(default_port);
|
||||
|
||||
PhFree(hostname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int growl_tcp_datagram( const char *server , const unsigned char *data , const int data_length )
|
||||
{
|
||||
int result;
|
||||
struct sockaddr_in serv_addr;
|
||||
SOCKET sock = 0;
|
||||
|
||||
if( growl_tcp_parse_hostname( server , 9887 , &serv_addr ) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if( sock == INVALID_SOCKET )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( sendto(sock, (char*)data , data_length , 0 , (struct sockaddr*)&serv_addr , sizeof(serv_addr) ) > 0 )
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
|
||||
closesocket(sock);
|
||||
return result;
|
||||
}
|
||||
14
plugins/ExtendedNotifications/gntp-send/tcp.h
Normal file
14
plugins/ExtendedNotifications/gntp-send/tcp.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _TCP_H_
|
||||
#define _TCP_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
void growl_tcp_write_raw( SOCKET sock, const unsigned char * data, const int data_length );
|
||||
void growl_tcp_write( SOCKET sock , const char *const format , ... ) __attribute__ ((format (printf, 2, 3)));
|
||||
char* growl_tcp_read(SOCKET sock);
|
||||
SOCKET growl_tcp_open(const char* server);
|
||||
void growl_tcp_close(SOCKET sock);
|
||||
int growl_tcp_datagram( const char *server , const unsigned char *data , const int data_length );
|
||||
|
||||
#endif /* _TCP_H_ */
|
||||
Reference in New Issue
Block a user