📄 downloadmanager.cpp
字号:
}
//char path[255];
//uint32 length = sizeof(path);
//URLToFilePath(url, path, &length);
//unlink(path);
}
return result;
}
// Utility Functions
bool DownloadManager::IsEmpty()
{
bool result;
m_mutex.Acquire();
result = m_itemList.empty();
m_mutex.Release();
return result;
}
uint32 DownloadManager::CountItems()
{
uint32 result;
m_mutex.Acquire();
result = m_itemList.size();
m_mutex.Release();
return result;
}
DownloadItem* DownloadManager::ItemAt(uint32 index)
{
DownloadItem* result = NULL;
m_mutex.Acquire();
index = CheckIndex(index);
if(index != kInvalidIndex)
{
result = m_itemList[index];
}
m_mutex.Release();
return result;
}
uint32 DownloadManager::IndexOf(DownloadItem* item)
{
return InternalIndexOf(&m_itemList, item);
}
uint32 DownloadManager::InternalIndexOf(vector<DownloadItem*>* list,
DownloadItem* item)
{
uint32 result = kInvalidIndex;
uint32 index = 0;
uint32 size = 0;
assert(list);
assert(item);
if(list && item)
{
size = list->size();
for(index = 0; index < size; index++)
{
if(item == (*list)[index])
{
result = index;
break;
}
}
}
return result;
}
bool DownloadManager::HasItem(DownloadItem* item)
{
return (IndexOf(item) != kInvalidIndex);
}
// Internal functions
inline uint32 DownloadManager::CheckIndex(uint32 index)
{
// If we're dealing with a bogus index then set it to -1.
if(index >= CountItems())
{
index = kInvalidIndex;
}
return index;
}
DownloadItem* DownloadManager::GetNextQueuedItem()
{
int i, total = 0;
if (m_downloadIndex < 0 || m_downloadIndex >= (int)m_itemList.size())
m_downloadIndex = 0;
for(i = m_downloadIndex, total = 0; i < (int)m_itemList.size();
i = (i + 1) % m_itemList.size(), total++)
{
if (total >= (int)m_itemList.size())
return NULL;
if (m_itemList[i]->GetState() == kDownloadItemState_Queued)
{
m_downloadIndex++;
return m_itemList[i];
}
}
return NULL;
}
static int32 GetContentLengthFromHeader(const char* buffer)
{
int32 result = -1;
char* cp = strstr(buffer, "Content-Length:");
if(cp)
{
cp += strlen("Content-Length:") + 1;
result = atoi(cp);
}
return result;
}
static void GetContentTimeFromHeader(const char* buffer, string &mTime)
{
char* cp = strstr(buffer, "Last-Modified:");
if(cp)
{
string::size_type pos;
cp += strlen("Last-Modified:") + 1;
mTime = string(cp);
pos = mTime.find(string("\r"), 0);
if (pos != string::npos)
mTime.erase(pos, mTime.length() - 2);
pos = mTime.find(string("\n"), 0);
if (pos != string::npos)
mTime.erase(pos, mTime.length() - 2);
}
else
mTime = string("");
}
const uint8 kHttpPort = 80;
const uint32 kMaxHostNameLen = 64;
const uint32 kMaxURLLen = 1024;
static bool IsHTTPHeaderComplete(char* buffer, uint32 length)
{
bool result = false;
//if(length >= 4)
//{
//if( (buffer[0] == 'H' && buffer[1] == 'T'
// && buffer[2] == 'T' && buffer[3] == 'P'))
//{
//cout << "buffer is HTTP" << endl;
for(char* cp = buffer; cp < buffer + length; cp++)
{
if(!strncmp(cp, "\n\n", 2) || !strncmp(cp, "\r\n\r\n", 4))
{
result = true;
break;
}
}
//}
//}
return result;
}
Error DownloadManager::Download(DownloadItem* item)
{
Error result = kError_InvalidParam;
assert(item);
if(item)
{
char hostname[kMaxHostNameLen + 1] = {0x00};
char proxyname[kMaxURLLen + 1] = {0x00};
unsigned short port;
struct sockaddr_in addr;
struct hostent host;
SOCKET s = -1;
char* file = NULL;
char* destPath = NULL;
bool useProxy;
struct stat st;
destPath = new char[_MAX_PATH];
uint32 length = _MAX_PATH;
m_context->prefs->GetPrefString(kSaveMusicDirPref, destPath, &length);
strcat(destPath, DIR_MARKER_STR);
strcat(destPath, item->DestinationFile().c_str());
if(-1 != stat(destPath, &st))
{
if ((unsigned int)st.st_size >= item->GetTotalBytes())
{
if(destPath)
delete [] destPath;
return kError_NoErr;
}
}
result = kError_ProtocolNotSupported;
// where should we connect to?
if(!strncasecmp(item->SourceURL().c_str(), "http://", 7))
{
int32 numFields;
uint32 length;
result = kError_NoErr;
m_context->prefs->GetPrefBoolean(kUseProxyPref, &useProxy);
if(useProxy)
{
char proxy[kMaxURLLen + 1] = {0x00};
length = sizeof(proxy);
m_context->prefs->GetPrefString(kProxyHostPref, proxy, &length);
numFields = sscanf(proxy,
"http://%[^:/]:%hu", proxyname, &port);
sscanf(item->SourceURL().c_str(),
"http://%[^:/]", hostname);
//strncpy(proxyname, item->SourceURL().c_str(), kMaxURLLen);
//proxyname[kMaxURLLen - 1] = 0;
file = (char*)item->SourceURL().c_str();
}
else
{
numFields = sscanf(item->SourceURL().c_str(),
"http://%[^:/]:%hu", hostname, &port);
file = strchr(item->SourceURL().c_str() + 7, '/');
}
if(numFields < 1)
{
result = kError_InvalidURL;
}
if(numFields < 2)
{
port = kHttpPort;
}
}
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
// get hostname
if(IsntError(result))
{
char* server = (*proxyname ? proxyname : hostname);
struct hostent* hostByName;
struct hostent hostByIP;
//*m_debug << "gethostbyname: " << hostname << endl;
hostByName = gethostbyname(server);
// 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((int)(ip = inet_addr(server)) < 0)
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));
}
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
}
// 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;
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
}
// connect and send request
if(IsntError(result))
{
Error err;
int ret;
err = Connect(s, (const struct sockaddr*)&addr, ret, item);
if (IsError(err))
result = kError_UserCancel;
if (ret < 0)
result = kError_ConnectFailed;
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
if(IsntError(result))
{
const char* kHTTPQuery = "GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"User-Agent: FreeAmp/%s\r\n";
const char* kRange = "Range: bytes=%lu-\r\n";
const char* kIfRange = "If-Range: %s\r\n";
const char* kCookie = "Cookie: %s\r\n";
// the magic 256 is enough for a time field that
// we got from the server
char* query = new char[ strlen(kHTTPQuery) +
strlen(file) +
strlen(hostname) +
strlen(FREEAMP_VERSION)+
(item->GetBytesReceived() ? (strlen(kRange) + 256): 0 ) +
(item->SourceCookie().size() ? (item->SourceCookie().size() + strlen(kCookie)): 0) +
2];
sprintf(query, kHTTPQuery, file, hostname, FREEAMP_VERSION);
// do we need to request a range?
if(item->GetBytesReceived())
{
if(-1 != stat(destPath, &st))
{
char* range = new char[strlen(kRange) + 256 + 1];
sprintf(range, kRange, item->GetBytesReceived());
strcat(query, range);
if (item->MTime().length() > 0)
{
sprintf(range, kIfRange, item->MTime().c_str());
strcat(query, range);
}
delete [] range;
}
else
{
item->SetBytesReceived(0);
item->SetMTime("");
}
}
if(item->SourceCookie().size())
{
char* cookie = new char[strlen(kCookie) + item->SourceCookie().size() + 1];
sprintf(cookie, kCookie, item->SourceCookie().c_str());
strcat(query, cookie);
delete [] cookie;
}
strcat(query, "\n");
int count;
err = Send(s, query, strlen(query), 0, count, item);
if (IsError(err))
result = kError_UserCancel;
if(count != (int)strlen(query))
{
result = kError_IOError;
}
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -