📄 httpcli.cpp
字号:
/* * by balancesli * balancesli@gmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <ctype.h>#include <netdb.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/time.h>#include <pthread.h>#include <assert.h>#include <linux/ip.h>#include "Utils.h"#include "HttpCli.h"#include "Task.h"#include "dget.h"#include "Utils.h"THttpCli :: THttpCli(TUrl * url) : Sckp(NULL){ up = url;} THttpCli :: ~THttpCli(void){ if(Sckp != NULL) delete Sckp;}uerr_t THttpCli :: Connect(void){ uerr_t err; if(Sckp == NULL) Sckp = new TSocketCli(up->HostName); err = Sckp->Connect(80); if(err != NOCONERROR) return err; else return HOK;} uerr_t THttpCli :: Disconnect(void){ int Sock; Sock = Sckp->GetSockfd(); close(Sock);}int THttpCli :: BufReadChar(int fd, char *ret){ int retval = Recv(fd, ret, 1, 0); if (retval <= 0) return retval; return 1;}int THttpCli :: BufPeek(int fd, char *ret){ int retval = Recv(fd, ret, 1, MSG_PEEK); if (retval <= 0) return retval; return 1;}uerr_t THttpCli :: FetchNextHeader(int fd, char **hdr){ int i, BufSize, retval; char Next; BufSize = DYNAMIC_LINE_BUFFER; *hdr = new char[DYNAMIC_LINE_BUFFER]; for (i = 0; 1; i++) { if (i > BufSize - 1) { char * t = new char[BufSize <<= 1]; strcpy(t, *hdr); delete []*hdr; *hdr = t; } retval = BufReadChar(fd, *hdr + i); if (retval == 1) { if ((*hdr)[i] == '\n') { if (!(i == 0 || (i == 1 && (*hdr)[0] == '\r'))) { retval = BufPeek(fd, &Next); if (retval == 0) return HEOF; else if (retval == -1) return HERR; if (Next == '\t' || Next == ' ') continue; } (*hdr)[i] = '\0'; if (i > 0 && (*hdr)[i - 1] == '\r') (*hdr)[i - 1] = '\0'; break; } } else if (retval == 0) return HEOF; else return HERR; } return HOK;}int THttpCli :: ParseStatLine(const char *hdr, const char **rp){ int Major, Minor; int StatusCode; const char *p; *rp = NULL; if(strncmp(hdr, "HTTP/", 5) != 0) return -1; hdr += 5; p = hdr; for (Major = 0; isdigit(*hdr); hdr++) Major = 10 * Major + (*hdr - '0'); if (*hdr != '.' || p == hdr) return -1; ++hdr; p = hdr; for (Minor = 0; isdigit(*hdr); hdr++) Minor = 10 * Minor + (*hdr - '0'); if (*hdr != ' ' || p == hdr) return -1; if (Major < 1) return -1; ++hdr; if (!(isdigit(*hdr) && isdigit(hdr[1]) && isdigit(hdr[2]))) return -1; StatusCode = 100 * (*hdr - '0') + 10 * (hdr[1] - '0') + (hdr[2] - '0'); if (hdr[3] != ' ') { if (!hdr[3]) *rp = hdr + 3; else return -1; } else *rp = hdr + 4; return StatusCode;}int THttpCli :: SkipLws(const char *hdr){ int i; for (i = 0; *hdr == ' ' || *hdr == '\t' || *hdr == '\r' || *hdr == '\n'; ++hdr) ++i; return i;}long THttpCli :: GetLen(const char *hdr){ const int l = 15; //strlen("content-length:") long Len; if (strncasecmp(hdr, "content-length:", l)) return -1; hdr += (l + SkipLws(hdr + l)); if (!*hdr) return -1; if (!isdigit(*hdr)) return -1; for (Len = 0; isdigit(*hdr); hdr++) Len = 10 * Len + (*hdr - '0'); return Len;}long THttpCli :: GetRange(const char *hdr){ const int l = 14; //strlen("content-range:") long Len; if(strncasecmp(hdr, "content-range:", l)) return -1; hdr += (l + SkipLws(hdr + l)); if(!*hdr) return -1; if(!strncasecmp(hdr, "bytes", 5)) { hdr += 5; hdr += SkipLws(hdr); if (!*hdr) return -1; } if(!isdigit(*hdr)) return -1; for(Len = 0; isdigit(*hdr); hdr++) Len = 10 * Len + (*hdr - '0'); return Len;}char * THttpCli :: GetLocation(const char *hdr){ static const int l = 9; // strlen("location:") if (strncasecmp(hdr, "location:", l)) return NULL; hdr += (l + SkipLws(hdr + l)); return strdup(hdr);}char * THttpCli :: GetModified(const char *hdr){ const int l = 14; //strlen("last-modified:") if (strncasecmp(hdr, "last-modified:", l)) return NULL; hdr += (l + SkipLws(hdr + l)); return strdup(hdr);}int THttpCli :: GetAcceptRanges(const char *hdr){ const int l = 14; //strlen("accept-ranges:") if (strncasecmp(hdr, "accept-ranges:", l)) return -1; hdr += (l + SkipLws(hdr + l)); if (strstr(hdr, "none")) return 0; else return 1;}uerr_t THttpCli :: GetHttpInfo(TUrl * up, HttpStat * hs){ uerr_t err; int Sock; char Buffer[HTTP_BUF_SIZE]; int Len; char * Path; Len = strlen(up->HostDirName) + strlen(up->HostFileName) + 2; Path = new char[Len]; sprintf(Path, "/%s/%s",up->HostDirName, up->HostFileName); // ShowMsg("%s\n", Path); err = Connect(); if(err != HOK) { ShowMsg("Error connecting to %s", up->HostName); return err; } Sock = Sckp->GetSockfd(); /* We will get http info about the file by calling http_fetch_headers */ /* with HEAD */ const char * www_auth = GetAuthStr(up->UserName, up->PassWord, "Authorization"); www_auth = www_auth ? www_auth : "" ;// sprintf(Buffer, // "HEAD %s HTTP/1.0\r\nUser-Agent: %s%s\r\nHost:%s\r\nAccept: */*\r\n\r\n", // Path, SOFTWARE_NAME, SOFTWARE_VERSION, up->HostName); sprintf(Buffer, "HEAD %s HTTP/1.0\r\nUser-Agent:%s%s\r\nHost:%s\r\nAccept:*/*\r\n%s\r\n%s\r\n", Path, SOFTWARE_NAME, SOFTWARE_VERSION, up->HostName, www_auth); err = FetchHeaders(Sock, up, hs, Buffer); close(Sock); delete []Path; return err;}/* function to fetch the http headers from the socket *//* to a specific command string */uerr_t THttpCli :: FetchHeaders(int Sock, TUrl * up, HttpStat * hs, char * Cmd){ uerr_t err; int BytesWritten, Count, StatusCode; char *hdr, *Type, *AllHdr; long ContentLen, ContentRange; int AllLength; const char *error; hs->Len = 0L; hs->ContentLen = -1; hs->AcceptRanges = -1; hs->Result = -1; hs->NewLoc = NULL; hs->RemoteTime = NULL; hs->Error = NULL; /* * send the command to the server */ BytesWritten = Send(Sock, Cmd, strlen(Cmd), 0); if (BytesWritten != strlen(Cmd)) { ShowMsg("Failed writing HTTP request"); return WRITEERR; } AllLength = 0; ContentLen = ContentRange = -1; StatusCode = -1; AllHdr = NULL; Type = NULL; /* * Header-fetching loop. */ Count = 0; for ( ; ; ) { ++Count; //Get the header. err = FetchNextHeader(Sock, &hdr); if (err == HEOF) { ShowMsg("End of file while parsing headers"); delete [] hdr; if(Type) delete []Type; if(AllHdr) delete []AllHdr; return HEOF; } else if (err == HERR) { ShowMsg("Read error in headers"); delete []hdr; if(Type) delete []Type; if(AllHdr) delete []AllHdr; return HERR; } if (!*hdr) { delete []hdr; break; } if (Count == 1) { StatusCode = ParseStatLine(hdr, &error); hs->StatusCode = StatusCode; //Store the descriptive response. if (StatusCode == -1) // malformed request hs->Error = strdup("UNKNOWN"); else if (!*error) hs->Error = strdup("(no description)"); else hs->Error = strdup(error); } if (ContentLen == -1) { ContentLen = GetLen(hdr); hs->ContentLen = ContentLen; } if (!hs->NewLoc) hs->NewLoc = GetLocation(hdr); if (!hs->RemoteTime) hs->RemoteTime = GetModified(hdr); if (hs->AcceptRanges == -1) { hs->AcceptRanges = GetAcceptRanges(hdr); } if (!hs->NewLoc) hs->NewLoc = GetLocation(hdr); delete []hdr; } if (H_20X(StatusCode)) return HOK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -