winamp/Src/replicant/jnetlib/util.cpp

186 lines
3.3 KiB
C++

/*
** 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;
}