1 // 2 // HtNNTP.cc 3 // 4 // HtNNTP: Interface classes for NNTP messaging 5 // 6 // Gabriele Bartolini - Prato - Italia 7 // started: 01.08.2000 8 // 9 // Including: 10 // - Generic class 11 // - Response message class 12 // 13 // Part of the ht://Dig package <http://www.htdig.org/> 14 // Copyright (c) 2000-2004 The ht://Dig Group 15 // For copyright details, see the file COPYING in your distribution 16 // or the GNU Library General Public License (LGPL) version 2 or later 17 // <http://www.gnu.org/copyleft/lgpl.html> 18 // 19 // $Id: HtNNTP.cc,v 1.5 2004/05/28 13:15:23 lha Exp $ 20 // 21 22 #ifdef HAVE_CONFIG_H 23 #include "htconfig.h" 24 #endif /* HAVE_CONFIG_H */ 25 26 #include "lib.h" 27 #include "Transport.h" 28 #include "HtNNTP.h" 29 30 #include <signal.h> 31 #include <sys/types.h> 32 #include <ctype.h> 33 #include <stdio.h> // for sscanf 34 35 // for setw() 36 #ifdef HAVE_STD 37 #include <iomanip> 38 #ifdef HAVE_NAMESPACES 39 using namespace std; 40 #endif 41 #else 42 #include <iomanip.h> 43 #endif /* HAVE_STD */ 44 45 #if 1 46 typedef void (*SIGNAL_HANDLER) (...); 47 #else 48 typedef SIG_PF SIGNAL_HANDLER; 49 #endif 50 51 // Stats information 52 int HtNNTP::_tot_seconds = 0; 53 int HtNNTP::_tot_requests = 0; 54 int HtNNTP::_tot_bytes = 0; 55 56 /////// 57 // HtNNTP_Response class 58 // 59 // Response message sent by the remote NNTP server 60 /////// 61 62 63 // Construction 64 HtNNTP_Response()65HtNNTP_Response::HtNNTP_Response() 66 { 67 68 } 69 70 71 // Destruction 72 ~HtNNTP_Response()73HtNNTP_Response::~HtNNTP_Response() 74 { 75 } 76 77 Reset()78void HtNNTP_Response::Reset() 79 { 80 81 // Call the base class method in order to reset 82 // the base class attributes 83 84 Transport_Response::Reset(); 85 86 } 87 88 89 90 91 /////// 92 // HtNNTP generic class 93 // 94 // 95 /////// 96 97 98 // Construction 99 HtNNTP()100HtNNTP::HtNNTP() 101 : Transport(new Connection()), 102 _bytes_read(0), 103 _useproxy(0) 104 { 105 } 106 107 // Destruction 108 ~HtNNTP()109HtNNTP::~HtNNTP() 110 { 111 // Free the connection 112 // 113 CloseConnection(); 114 if (_connection) 115 delete _connection; 116 _connection = 0; 117 } 118 119 120 /////// 121 // Manages the requesting process 122 /////// 123 Request()124Transport::DocStatus HtNNTP::Request() 125 { 126 127 DocStatus result = Document_ok; 128 _response.Reset(); // Reset the response 129 130 return result; 131 132 } 133 134 SetRequestCommand(String & cmd)135void HtNNTP::SetRequestCommand(String &cmd) 136 { 137 138 cmd << "\r\n"; 139 140 } 141 142 143 144 145 //***************************************************************************** 146 // int HtNNTP::ParseHeader() 147 // Parse the header of the document 148 // ParseHeader()149int HtNNTP::ParseHeader() 150 { 151 String line = 0; 152 int inHeader = 1; 153 154 if (_response._modification_time) 155 { 156 delete _response._modification_time; 157 _response._modification_time=NULL; 158 } 159 while (inHeader) 160 { 161 162 line.trunc(); 163 164 if(! _connection->Read_Line(line, "\n")) 165 return -1; // Connection down 166 167 _bytes_read+=line.length(); 168 line.chop('\r'); 169 170 if (line.length() == 0) 171 inHeader = 0; 172 else 173 { 174 // Found a not-empty line 175 176 if (debug > 3) 177 cout << "Header line: " << line << endl; 178 179 // Status - Line check 180 char *token = line.get(); 181 182 while (*token && !isspace(*token)) 183 token++; 184 185 while (*token && isspace(*token)) 186 token++; 187 } 188 } 189 190 if (_response._modification_time == NULL) 191 { 192 if (debug > 3) 193 cout << "No modification time returned: assuming now" << endl; 194 195 //Set the modification time 196 _response._modification_time = new HtDateTime; 197 _response._modification_time->ToGMTime(); // Set to GM time 198 199 } 200 201 return 1; 202 203 } 204 205 GetDocumentStatus(HtNNTP_Response & r)206HtNNTP::DocStatus HtNNTP::GetDocumentStatus(HtNNTP_Response &r) 207 { 208 209 // Let's give a look at the return status code 210 211 HtNNTP::DocStatus returnStatus=Document_not_found; 212 int statuscode; 213 214 statuscode=r.GetStatusCode(); 215 216 if(statuscode==200) 217 { 218 returnStatus = Document_ok; // OK 219 } 220 221 // Exit the function 222 return returnStatus; 223 224 } 225 226 ReadBody()227int HtNNTP::ReadBody() 228 { 229 230 _response._contents = 0; // Initialize the string 231 232 char docBuffer[8192]; 233 int bytesRead = 0; 234 int bytesToGo = _response._content_length; 235 236 if (bytesToGo < 0 || bytesToGo > _max_document_size) 237 bytesToGo = _max_document_size; 238 239 if( _connection == NULL ) 240 { 241 cout << "HtNNTP::ReadBody: _connection is NULL\n"; 242 exit(0); 243 } 244 245 246 while (bytesToGo > 0) 247 { 248 int len = bytesToGo< (int)sizeof(docBuffer) ? bytesToGo : (int)sizeof(docBuffer); 249 bytesRead = _connection->Read(docBuffer, len); 250 if (bytesRead <= 0) 251 break; 252 253 _response._contents.append(docBuffer, bytesRead); 254 255 bytesToGo -= bytesRead; 256 257 _bytes_read+=bytesRead; 258 259 } 260 261 // Set document length 262 _response._document_length = _response._contents.length(); 263 264 return bytesRead; 265 266 } 267 268 269 /////// 270 // Show the statistics 271 /////// 272 ShowStatistics(ostream & out)273ostream &HtNNTP::ShowStatistics (ostream &out) 274 { 275 Transport::ShowStatistics(out); // call the base class method 276 277 out << " NNTP Requests : " << GetTotRequests() << endl; 278 out << " NNTP KBytes requested : " << (double)GetTotBytes()/1024 << endl; 279 out << " NNTP Average request time : " << GetAverageRequestTime() 280 << " secs" << endl; 281 282 out << " NNTP Average speed : " << GetAverageSpeed()/1024 283 << " KBytes/secs" << endl; 284 285 return out; 286 } 287