00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef _WIN32
00031 #pragma warning(disable:4786)
00032 #pragma warning(disable:4503)
00033 #else
00034 #include <errno.h>
00035 #include <ctype.h>
00036 #endif
00037 #include "ISocketHandler.h"
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include "Parse.h"
00041 #include "Utility.h"
00042
00043 #include "HttpPostSocket.h"
00044
00045
00046 #ifdef SOCKETS_NAMESPACE
00047 namespace SOCKETS_NAMESPACE {
00048 #endif
00049
00050
00051 HttpPostSocket::HttpPostSocket(ISocketHandler& h) : HttpClientSocket(h)
00052 ,m_bMultipart(false)
00053 {
00054 }
00055
00056
00057 HttpPostSocket::HttpPostSocket(ISocketHandler& h,const std::string& url_in) : HttpClientSocket(h, url_in)
00058 ,m_bMultipart(false)
00059 {
00060 m_boundary = "----";
00061 for (int i = 0; i < 12; i++)
00062 {
00063 char c = 0;
00064 while (!isalnum(c))
00065 {
00066 c = (char)(Random() % 96 + 32);
00067 }
00068 m_boundary += c;
00069 }
00070 }
00071
00072
00073 HttpPostSocket::~HttpPostSocket()
00074 {
00075 }
00076
00077
00078 void HttpPostSocket::AddField(const std::string& name,const std::string& value)
00079 {
00080 std::list<std::string> vec;
00081 vec.push_back(value);
00082 AddMultilineField(name, vec);
00083 }
00084
00085
00086 void HttpPostSocket::AddMultilineField(const std::string& name,std::list<std::string>& values)
00087 {
00088 m_fields[name] = values;
00089 }
00090
00091
00092 void HttpPostSocket::AddFile(const std::string& name,const std::string& filename,const std::string& type)
00093 {
00094 struct stat st;
00095 if (!stat(filename.c_str(), &st))
00096 {
00097 m_files[name] = filename;
00098 m_content_length[filename] = st.st_size;
00099 m_content_type[filename] = type;
00100 m_bMultipart = true;
00101 }
00102 else
00103 {
00104 Handler().LogError(this, "AddFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00105 SetCloseAndDelete();
00106 }
00107 }
00108
00109
00110 void HttpPostSocket::Open()
00111 {
00112
00113 TcpSocket::Open(GetUrlHost(), GetUrlPort());
00114 }
00115
00116
00117 void HttpPostSocket::OnConnect()
00118 {
00119 if (m_bMultipart)
00120 {
00121 DoMultipartPost();
00122 }
00123 else
00124 {
00125 std::string body;
00126
00127
00128 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
00129 {
00130 std::string name = (*it).first;
00131 std::list<std::string>& ref = (*it).second;
00132 if (body.size())
00133 {
00134 body += '&';
00135 }
00136 body += name + "=";
00137 bool first = true;
00138 for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
00139 {
00140 std::string value = *it;
00141 if (!first)
00142 {
00143 body += "%0d%0a";
00144 }
00145 body += Utility::rfc1738_encode(value);
00146 first = false;
00147 }
00148 }
00149
00150
00151 SetMethod("POST");
00152 SetHttpVersion( "HTTP/1.1" );
00153 AddResponseHeader( "Host", GetUrlHost() );
00154 AddResponseHeader( "User-agent", MyUseragent());
00155 AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
00156 AddResponseHeader( "Connection", "close" );
00157 AddResponseHeader( "Content-type", "application/x-www-form-urlencoded" );
00158 AddResponseHeader( "Content-length", Utility::l2string((long)body.size()) );
00159 SendRequest();
00160
00161
00162 Send( body );
00163 }
00164 }
00165
00166
00167 void HttpPostSocket::DoMultipartPost()
00168 {
00169 long length = 0;
00170 std::string tmp;
00171
00172
00173 {
00174 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
00175 {
00176 std::string name = (*it).first;
00177 std::list<std::string>& ref = (*it).second;
00178 tmp = "--" + m_boundary + "\r\n"
00179 "content-disposition: form-data; name=\"" + name + "\"\r\n"
00180 "\r\n";
00181 for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
00182 {
00183 std::string value = *it;
00184 tmp += value + "\r\n";
00185 }
00186 length += (long)tmp.size();
00187 }
00188 }
00189
00190
00191 {
00192 for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++)
00193 {
00194 std::string name = (*it).first;
00195 std::string filename = (*it).second;
00196 long content_length = m_content_length[filename];
00197 std::string content_type = m_content_type[filename];
00198 tmp = "--" + m_boundary + "\r\n"
00199 "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
00200 "content-type: " + content_type + "\r\n"
00201 "\r\n";
00202 length += (long)tmp.size();
00203 length += content_length;
00204 length += 2;
00205 }
00206 }
00207
00208
00209 tmp = "--" + m_boundary + "--\r\n";
00210 length += (long)tmp.size();
00211
00212
00213 SetMethod("POST");
00214 SetHttpVersion( "HTTP/1.1" );
00215 AddResponseHeader( "Host", GetUrlHost() );
00216 AddResponseHeader( "User-agent", MyUseragent());
00217 AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
00218 AddResponseHeader( "Connection", "close" );
00219 AddResponseHeader( "Content-type", "multipart/form-data; boundary=" + m_boundary );
00220 AddResponseHeader( "Content-length", Utility::l2string(length) );
00221
00222 SendRequest();
00223
00224
00225 {
00226 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
00227 {
00228 std::string name = (*it).first;
00229 std::list<std::string>& ref = (*it).second;
00230 tmp = "--" + m_boundary + "\r\n"
00231 "content-disposition: form-data; name=\"" + name + "\"\r\n"
00232 "\r\n";
00233 for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
00234 {
00235 std::string value = *it;
00236 tmp += value + "\r\n";
00237 }
00238 Send( tmp );
00239 }
00240 }
00241
00242
00243 {
00244 for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++)
00245 {
00246 std::string name = (*it).first;
00247 std::string filename = (*it).second;
00248 std::string content_type = m_content_type[filename];
00249 tmp = "--" + m_boundary + "\r\n"
00250 "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
00251 "content-type: " + content_type + "\r\n"
00252 "\r\n";
00253 Send( tmp );
00254 {
00255 FILE *fil = fopen(filename.c_str(),"rb");
00256 if (fil)
00257 {
00258 char slask[2000];
00259 size_t n;
00260 while ((n = fread(slask, 1, 2000, fil)) > 0)
00261 {
00262 SendBuf(slask, n);
00263 }
00264 fclose(fil);
00265 }
00266 }
00267 Send("\r\n");
00268 }
00269 }
00270
00271
00272 Send("--" + m_boundary + "--\r\n");
00273 }
00274
00275
00276 void HttpPostSocket::SetMultipart()
00277 {
00278 m_bMultipart = true;
00279 }
00280
00281
00282 #ifdef SOCKETS_NAMESPACE
00283 }
00284 #endif
00285