diff options
Diffstat (limited to 'Src/replicant/jnetlib/util.cpp')
-rw-r--r-- | Src/replicant/jnetlib/util.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/Src/replicant/jnetlib/util.cpp b/Src/replicant/jnetlib/util.cpp new file mode 100644 index 00000000..3b2b5a11 --- /dev/null +++ b/Src/replicant/jnetlib/util.cpp @@ -0,0 +1,185 @@ +/* +** JNetLib +** Copyright (C) 2000-2007 Nullsoft, Inc. +** Author: Justin Frankel +** File: util.cpp - JNL implementation of basic network utilities +** License: see jnetlib.h +*/ + +#include "netinc.h" +#include "util.h" +#include "foundation/error.h" +#ifdef USE_SSL +#include "sslconnection.h" +#ifdef _WIN32 +#include <wincrypt.h> +#endif +#include <openssl/rand.h> + +#ifdef _WIN32 +static HCRYPTPROV GetKeySet() +{ + HCRYPTPROV hCryptProv; + LPCWSTR UserName = L"WinampKeyContainer"; // name of the key container + + if (CryptAcquireContext( + &hCryptProv, // handle to the CSP + UserName, // container name + NULL, // use the default provider + PROV_RSA_FULL, // provider type + 0)) // flag values + { + return hCryptProv; + } + else if (CryptAcquireContext( + &hCryptProv, + UserName, + NULL, + PROV_RSA_FULL, + CRYPT_NEWKEYSET)) + { + return hCryptProv; + } + else + return 0; +} +#endif + +static void InitSSL() +{ + SSL_load_error_strings(); + SSL_library_init(); +#ifdef _WIN32 + HCRYPTPROV hCryptProv = GetKeySet(); + if (hCryptProv) + { + BYTE pbData[8*sizeof(unsigned long)] = {0}; + if (CryptGenRandom(hCryptProv, 8*sizeof(unsigned long), pbData)) + { + RAND_seed(pbData, 16); + } + CryptReleaseContext(hCryptProv,0); + } +#endif +// sslContext = SSL_CTX_new(SSLv23_client_method()); +// SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL); + +// SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF); +} +static int open_ssl_initted = 0; +#endif + +static int was_initted = 0; + +int JNL::open_socketlib() +{ +#ifdef _WIN32 + if (!was_initted) + { + WSADATA wsaData = {0}; + if (WSAStartup(MAKEWORD(1, 1), &wsaData)) + { + return NErr_Error; + } + } +#endif +#ifdef USE_SSL + if (!open_ssl_initted) + { + InitSSL(); + open_ssl_initted=1; + } +#endif + return NErr_Success; +} + +void JNL::close_socketlib() +{ +#ifdef _WIN32 + if (was_initted) + { + WSACleanup(); + } +#ifdef USE_SSL + // TODO need to do some reference counting to free this correctly + //SSL_CTX_free(sslContext); +#endif +#endif +} + +static char *jnl_strndup(const char *str, size_t n) +{ + char *o = (char *)calloc(n+1, sizeof(char)); + if (!o) + { + return 0; + } + strncpy(o, str, n); + o[n]=0; + return o; +} + +int JNL::parse_url(const char *url, char **prot, char **host, unsigned short *port, char **req, char **lp) +{ + free(*prot); *prot=0; + free(*host); *host = 0; + free(*req); *req = 0; + free(*lp); *lp = 0; + *port = 0; + + const char *p; + const char *protocol = strstr(url, "://"); + if (protocol) + { + *prot = jnl_strndup(url, protocol-url); + p = protocol + 3; + } + else + { + p = url; + } + + while (p && *p && *p == '/') p++; // skip extra / + + size_t end = strcspn(p, "@/"); + + // check for username + if (p[end] == '@') + { + *lp = jnl_strndup(p, end); + p = p+end+1; + end = strcspn(p, "[:/"); + } + + if (p[0] == '[') // IPv6 style address + { + p++; + const char *ipv6_end = strchr(p, ']'); + if (!ipv6_end) + return NErr_Malformed; + + *host = jnl_strndup(p, ipv6_end-p); + p = ipv6_end+1; + } + else + { + end = strcspn(p, ":/"); + *host = jnl_strndup(p, end); + p += end; + } + + // is there a port number? + if (p[0] == ':') + { + char *new_end; + *port = (unsigned short)strtoul(p+1, &new_end, 10); + p = new_end; + } + + if (p[0]) + { + *req = _strdup(p); + } + + return NErr_Success; +} |