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