11 #include <drift/dslcore.h>
12 #include <drift/download.h>
13 #include <drift/base64.h>
14 #include <drift/GenLib.h>
15 #include <drift/Threading.h>
17 DSL_Download_NoCurl::DSL_Download_NoCurl(
const string& url,
DSL_Download_Callback callback,
const string& user,
const string& pass,
void * user_ptr) {
18 user_agent =
"DSL HTTP Downloader Class (Mozilla)";
20 SetCallback(callback, user_ptr);
22 SetUserPass(user, pass);
25 DSL_Download_NoCurl::~DSL_Download_NoCurl() {
37 bool DSL_Download_NoCurl::SetURL(
const string& purl) {
38 if (purl.length() < 8 || strncmp(purl.c_str(),
"http://", 7)) {
39 this->error = TD_INVALID_PROTOCOL;
48 char * murl = dsl_strdup(purl.c_str());
49 char * begin = murl + 7;
52 char *p = strchr(begin,
'@');
56 char * q = strchr(begin,
':');
60 SetUserPass(begin, q);
62 SetUserPass(begin,
"");
66 p = strchr(host,
'/');
74 p = strchr(host,
':');
81 if (this->host.empty() || this->path.empty() || port == 0) {
82 this->error = TD_INVALID_URL;
87 printf(
"host: %s, port: %u, path: %s\n", this->host.c_str(), port, this->path.c_str());
93 bool DSL_Download_NoCurl::GetURL(
string& str) {
94 if (host.length() && path.length() && port) {
97 if (user.length() || pass.length()) {
98 url << user <<
":" << pass <<
"@";
100 url << host <<
":" << port << path;
101 str = std::move(url.str());
107 void DSL_Download_NoCurl::SetUserPass(
const string& puser,
const string& ppass) {
116 void DSL_Download_NoCurl::FollowRedirects(
bool follow) {
117 followRedirects = follow;
120 void DSL_Download_NoCurl::SetUserAgent(
const string& ua) {
127 if (this->error != TD_NO_ERROR) {
return false; }
129 D_SOCKET * sock = socks->Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);
131 this->error = TD_ERROR_CREATING_SOCKET;
135 uint32 ctimeo = timeo;
136 if (ctimeo == 0) { ctimeo = 60000; }
138 this->error = TD_ERROR_CONNECTING;
144 req <<
"GET " << path <<
" HTTP/1.0\r\n";
145 req <<
"Host: " << host <<
" : " << port <<
"\r\n";
146 req <<
"User-Agent: " << user_agent <<
"\r\n";
147 req <<
"Connection: close\r\n";
149 if (user.length() || pass.length()) {
150 string auth =
mprintf(
"%s:%s", user.c_str(), pass.c_str());
151 size_t len = base64_encode_buffer_size(auth.length());
154 req <<
"Authorization: Basic " << tmp <<
"\r\n";
161 socks->SetRecvTimeout(sock, timeo);
162 socks->SetSendTimeout(sock, timeo);
164 if (socks->Send(sock, req.str().c_str(), (
int)req.str().length()) < (
int)req.str().length()) {
165 this->error = TD_TIMEOUT;
170 uint64 got = 0, fullsize = 0;
172 int n=0,ln=0,tries=0;
173 char buf[16384] = { 0 };
174 while ((n = socks->RecvLine(sock,buf,16384)) >= RL3_NOLINE) {
175 if (n == RL3_NOLINE) {
177 this->error = TD_INVALID_RESPONSE;
182 safe_sleep(100,
true);
187 while (buf[strlen(buf) - 1] ==
'\n') { buf[strlen(buf) - 1] = 0; }
188 while (buf[strlen(buf) - 1] ==
'\r') { buf[strlen(buf) - 1] = 0; }
189 while (buf[strlen(buf) - 1] ==
'\n') { buf[strlen(buf) - 1] = 0; }
190 if (strlen(buf) == 0) {
break; }
194 if (strstr(buf,
"401")) {
195 this->error = TD_BAD_USER_PASS;
199 if (strstr(buf,
"404")) {
200 this->error = TD_FILE_NOT_FOUND;
204 if (!strstr(buf,
"200") && !strstr(buf,
"302")) {
205 this->error = TD_INVALID_RESPONSE;
211 if (!strnicmp(buf,
"Content-Length:",strlen(
"Content-Length:"))) {
212 char * p = buf + strlen(
"Content-Length:");
213 if (p[0] ==
' ') { p++; }
214 fullsize = atoi64(p);
215 if (callback != NULL && !callback(0, fullsize, u_ptr)) {
216 this->error = TD_CALLBACK_ABORT;
222 if (!strnicmp(buf,
"Location:",strlen(
"Location:"))) {
223 char * p = buf + strlen(
"Location:");
224 if (p[0] ==
' ') { p++; }
226 if (followRedirects) {
229 string url =
mprintf(
"http://%s:%u%s", host.c_str(), this->port, path.c_str());
232 dl->SetUserAgent(user_agent);
233 if (dl->GetError() == TD_NO_ERROR) {
235 this->error = dl->GetError();
239 this->error = dl->GetError();
245 this->error = TD_REDIRECT;
251 while ((n = socks->Recv(sock, buf, 16384)) > 0) {
253 if (fWriteTo->
write(buf, n, fWriteTo) < n) {
254 this->error = TD_FILE_WRITE_ERROR;
259 if (callback != NULL && !callback(got, fullsize, u_ptr)) {
260 this->error = TD_CALLBACK_ABORT;
virtual bool Download(DSL_FILE *fWriteTo)
virtual void SetTimeout(uint32 millisec)
virtual bool ConnectWithTimeout(DSL_SOCKET *sock, const char *host, int port, uint32 timeout)
Connect with timeout in milliseconds.
DSL_API int DSL_CC base64_encode(const void *inBuffer, size_t count, char *outBuffer)
bool(* DSL_Download_Callback)(uint64 got, uint64 fullsize, void *user_ptr)
DSL_API_CLASS string mprintf(const string fmt,...)
DSL_API void DSL_CC dsl_free(void *ptr)
DSL_API void *DSL_CC dsl_zmalloc(size_t lSize)
int64(* write)(void *buf, int64 size, DSL_FILE *fp)