?? http.cpp
字號:
/*____________________________________________________________________________
FreeAmp - The Free MP3 Player
Copyright (C) 2000 EMusic.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: Http.cpp,v 1.21 2000/12/30 22:55:07 robert Exp $
____________________________________________________________________________*/
#include "config.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <io.h>
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#endif
#if defined(unix) || defined(__BEOS__) || defined(_BSD_SOURCE)
#define SOCKET int
#endif
#if defined(unix) || defined(_BSD_SOURCE)
#include <arpa/inet.h>
#define closesocket(x) close(x)
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif
#ifdef __QNX__
#include <strings.h>
#endif
#include "Http.h"
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
const unsigned short kHttpPort = 80;
const unsigned int kMaxHostNameLen = 64;
const unsigned int kMaxURLLen = 1024;
const unsigned int kBufferSize=8192;
#define DB printf("%s:%d\n", __FILE__, __LINE__);
Http::Http(FAContext *context)
{
m_exit = false;
m_context = context;
m_file = NULL;
m_buffer = NULL;
m_bytesInBuffer = 0;
m_bufferSize = 0;
}
Http::~Http(void)
{
if (m_buffer)
delete m_buffer;
if (m_file)
fclose(m_file);
}
Error Http::DownloadToString(const string &url, string &page)
{
Error eRet;
eRet = Download(url, false);
if (IsntError(eRet))
page = string((char *)m_buffer, m_bytesInBuffer);
if (m_buffer)
{
delete m_buffer;
m_buffer = NULL;
}
return eRet;
}
Error Http::DownloadToFile(const string &url, const string &destPath)
{
Error eRet;
m_destPath = destPath;
eRet = Download(url, true);
if (m_file)
{
fclose(m_file);
m_file = NULL;
}
return eRet;
}
int Http::WriteToBuffer(unsigned char *buffer, unsigned int size)
{
if (m_buffer == NULL)
{
m_bufferSize = kBufferSize;
m_buffer = new unsigned char[m_bufferSize];
}
if (m_bytesInBuffer + size > m_bufferSize)
{
unsigned char *pTemp;
m_bufferSize += (kBufferSize < size) ? kBufferSize : kBufferSize + size;
pTemp = new unsigned char[m_bufferSize];
memcpy(pTemp, m_buffer, m_bytesInBuffer);
delete m_buffer;
m_buffer = pTemp;
}
memcpy(m_buffer + m_bytesInBuffer, buffer, size);
m_bytesInBuffer += size;
return size;
}
int Http::WriteToFile(unsigned char *buffer, unsigned int size)
{
if (m_file == NULL)
{
m_file = fopen(m_destPath.c_str(), "wb");
if (m_file == NULL)
return -1;
}
return fwrite(buffer, sizeof(unsigned char), size, m_file);
}
static void
EncodeURI(string & URI)
{
string::size_type convert = 0;
const char *legalCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/?.";
if (strncmp(URI.c_str(), "http://", 7) == 0)
convert = URI.find(string("/"), 7);
while ((convert = URI.find_first_not_of(legalCharacters, convert)) !=
string::npos)
{
string hex = "%";
char num[8];
// Do not replace %## sequences -- they are already encoded and
// ready to roll
if (URI[convert] == '%' && URI.length() - convert > 2 &&
isdigit(URI[convert + 1]) &&
isdigit(URI[convert + 2]))
{
convert++;
continue;
}
sprintf(num, "%02x", URI[convert] & 0xFF);
hex += num;
URI.replace(convert, 1, hex);
convert += hex.length();
}
}
Error Http::Download(const string &url, bool fileDownload)
{
Error result = kError_InvalidParam;
char hostname[kMaxHostNameLen + 1];
char localname[kMaxHostNameLen + 1];
char proxyname[kMaxURLLen + 1];
unsigned short port;
struct sockaddr_in addr;
struct hostent host;
SOCKET s = -1;
string file;
bool useProxy;
unsigned int bytesReceived = 0;
result = kError_ProtocolNotSupported;
// where should we connect to?
if(!strncasecmp(url.c_str(), "http://", 7))
{
int32 numFields;
uint32 length;
result = kError_NoErr;
m_context->prefs->GetPrefBoolean(kUseProxyPref, &useProxy);
length = sizeof(proxyname);
m_context->prefs->GetPrefString(kProxyHostPref, proxyname, &length);
if(useProxy)
{
numFields = sscanf(proxyname,
"http://%[^:/]:%hu", hostname, &port);
strcpy(proxyname, url.c_str());
file = string(proxyname);
}
else
{
const char *ptr;
numFields = sscanf(url.c_str(),
"http://%[^:/]:%hu", hostname, &port);
ptr = strchr(url.c_str() + 7, '/');
file = string(ptr ? ptr : "");
}
EncodeURI(file);
if(numFields < 1)
{
result = kError_InvalidURL;
}
if(numFields < 2)
{
port = kHttpPort;
}
}
// get hostname
if(IsntError(result))
{
struct hostent* hostByName;
struct hostent hostByIP;
//*m_debug << "gethostbyname: " << hostname << endl;
hostByName = gethostbyname(hostname);
// On some stacks a numeric IP address
// will not parse with gethostbyname.
// If that didn't work try to convert it as a
// numeric address before giving up.
if(!hostByName)
{
static unsigned long ip;
static char *addr_ptr[2] = {(char*)&ip, NULL};
if((ip = inet_addr(hostname)) == INADDR_NONE)
result = kError_CantFindHost;
else
{
hostByIP.h_length = sizeof(uint32);
hostByIP.h_addrtype = AF_INET;
hostByIP.h_addr_list = (char**)&addr_ptr;
hostByName = &hostByIP;
}
}
if(IsntError(result))
{
memcpy(&host, hostByName, sizeof(struct hostent));
}
}
// open socket
if(IsntError(result))
{
memset(&addr, 0x00, sizeof(struct sockaddr_in));
memcpy(&addr.sin_addr, host.h_addr, host.h_length);
addr.sin_family= host.h_addrtype;
addr.sin_port= htons(port);
//*m_debug << "socket" << endl;
s = socket(host.h_addrtype, SOCK_STREAM, 0);
if(s < 0)
result = kError_CantCreateSocket;
}
// connect and send request
if(IsntError(result))
{
Error err;
int ret;
err = Connect(s, (struct sockaddr*)&addr, ret);
if (IsError(err))
result = kError_UserCancel;
if (ret < 0)
result = kError_ConnectFailed;
if(IsntError(result))
{
gethostname(localname, kMaxHostNameLen);
const char* kHTTPQuery = "GET %s HTTP/1.0\r\n"
"Host: %s:80\r\n"
"User-Agent: FreeAmp/%s\r\n"
"Accept: */*\r\n";
// the magic 256 is enough for a time field that
// we got from the server
char* query = new char[ strlen(kHTTPQuery) +
file.length() +
strlen(hostname) +
strlen(FREEAMP_VERSION)+
2];
sprintf(query, kHTTPQuery, file.c_str(), hostname, FREEAMP_VERSION);
strcat(query, "\r\n");
int count;
err = Send(s, query, strlen(query), 0, count);
if (IsError(err))
result = kError_UserCancel;
if(count != (int)strlen(query))
{
result = kError_IOError;
}
delete [] query;
}
}
// receive response
if(IsntError(result))
{
uint32 bufferSize = 2048;
char* buffer = NULL;
int count;
uint32 total = 0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -