Changeset 3810
- Timestamp:
- 2003-03-09T09:08:58+13:00 (21 years ago)
- Location:
- trunk/gsdl/src/w32server
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gsdl/src/w32server/cgiwrapper.cpp
r3020 r3810 689 689 char *mimec = mime.getcstr(); 690 690 if (send_header(mimec, RInfo) >= 0) { 691 if ( strcmpi(RFields->MethodStr, "HEAD") != 0) {691 if (RFields->MethodStr != "HEAD") { 692 692 for (;;) { 693 693 nr = fread(buffer, 1, 2048, thefile); -
trunk/gsdl/src/w32server/httpreq.cpp
r3056 r3810 26 26 *********************************************************************/ 27 27 28 #include "text_t.h"29 28 #include <windows.h> 30 29 #include <stdlib.h> … … 32 31 #include <string.h> 33 32 #include <memory.h> 34 # pragma hdrstop33 #include "httpreq.h" 35 34 #include "parse.h" 36 35 #include "netio.h" 37 36 #include "settings.h" 38 #include "httpreq.h" //Had to put myself here because of the global types...39 37 #include "httpsrv.h" 40 38 #include "httpsend.h" … … 54 52 #define IO_BUFFER_SIZE 16384 //16K IO Buffer 55 53 #define MAX_HTTP_LINE_LEN 1024 //Max length of line in a header of 1024 56 #define MAX_HTTP_FIELD_NAME_LEN 128 //Max length of name field in line57 #define MAX_HTTP_FIELD_LEN 1024 //Max length of data in line58 54 59 55 //Private Function Declarations with Return Contstants … … 219 215 int GetHTTPHeaders(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields) { 220 216 //Parsing and IO buffers 221 char CurLine[NETIO_MAX_LINE];222 char NextLine[NETIO_MAX_LINE];223 char FieldNameStr[MAX_HTTP_FIELD_NAME_LEN];224 char FieldValStr[MAX_HTTP_FIELD_LEN];217 text_t CurLine; 218 text_t NextLine; 219 text_t FieldNameStr; 220 text_t FieldValStr; 225 221 226 222 //Parsing and IO working vars 227 223 int ReadBufferIndex; 228 224 int DataInBuffer; 229 int Start; 230 int End; 231 int Len; 225 text_t::const_iterator next; 226 text_t::const_iterator end; 232 227 233 228 //Clear all the fields … … 245 240 RequestInfo.IOBufferSize, ReadBufferIndex, DataInBuffer, 246 241 RequestInfo.ThreadNum) != 0) return GH_ERROR; 247 if ((NextLine[0] == ' ') || (NextLine[0] == '\t')) 248 strcat(CurLine, NextLine); 249 } while ((NextLine[0] == ' ') || (NextLine[0] == '\t')); 242 if ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t')) { 243 CurLine += NextLine; 244 } 245 } while ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t')); 250 246 //Method String (first word) 251 Start = 0; 252 GetWord(RequestFields.MethodStr, CurLine, Start, End); 253 CharUpper(RequestFields.MethodStr); 247 GetWord(RequestFields.MethodStr, CurLine.begin(), CurLine.end(), next); 248 uc(RequestFields.MethodStr); 254 249 255 250 /* Added Feb 2002 - IE since about version 5 send stupid frontpage requests 256 251 for MS Document formats eg "GET /_vti_inf.html" */ 257 if ( strcmp(RequestFields.MethodStr,"OPTIONS")==0) {258 252 if (RequestFields.MethodStr == "OPTIONS") { 253 return GH_BAD_METHOD; 259 254 } 260 255 //Version String (last word) 261 GetLastWord(RequestFields.VersionStr, CurLine, Start); 262 CharUpper(RequestFields.VersionStr); 263 264 if (strncmp(RequestFields.VersionStr, "HTTP/", 5) != 0) { 256 GetLastWord(RequestFields.VersionStr, CurLine.begin(), CurLine.end(), end); 257 uc(RequestFields.VersionStr); 258 text_t::const_iterator versionbegin = RequestFields.VersionStr.begin(); 259 260 if ((RequestFields.VersionStr.size() > 5) && (substr(versionbegin, versionbegin+5) != "HTTP/")) { 265 261 //No version, assume simple request 266 262 //part after method is URI 267 for (int i = 0; i < strlen(CurLine); i++) { 268 RequestFields.URIStr.push_back(CurLine[i]); 269 } 263 RequestFields.URIStr = CurLine; 270 264 return GH_SIMPLE_REQUEST; 271 265 } … … 273 267 //URI String (in between End of first and Start of last) 274 268 //<Method> <WhiteSpace> <URI> <WhiteSpace> <Version> <CRLF> 275 // End^ Start^269 // next^ end^ 276 270 text_t spacebuffer; 277 for (int i = End; i < Start; i++) { 271 text_t::const_iterator here = next; 272 while (here != end) { 278 273 // do this to remove trailing space 279 if ( CurLine[i] == '') {280 spacebuffer.push_back( ' ');274 if (*here == ' ' || *here == '\t') { 275 spacebuffer.push_back(*here); 281 276 } else { 282 277 if (!spacebuffer.empty()) { … … 284 279 spacebuffer.clear(); 285 280 } 286 RequestFields.URIStr.push_back(CurLine[i]); 287 } 281 RequestFields.URIStr.push_back(*here); 282 } 283 here++; 288 284 } 289 285 290 286 //Only accept requests from HTTP/0.9 or HTTP/1.X clients, we'll 291 287 //assume that anything else will require an upgrade or patch 292 if ( strncmp(RequestFields.VersionStr, "HTTP/1.", 7) != 0)288 if ((RequestFields.VersionStr.size() > 7) && (substr(versionbegin, versionbegin+7) != "HTTP/1.")) { 293 289 return GH_UNKNOWN_VERSION; 290 } 294 291 295 292 //Get the rest of the lines 296 297 strcpy(CurLine, NextLine); 298 299 while (CurLine[0] != 0) {//Blank Line, we're done 293 CurLine = NextLine; 294 295 while (!CurLine.empty()) {//Blank Line, we're done 300 296 do {//Get Next Line, append it if the first charactor is space 301 297 if (GetLine(NextLine, RequestInfo.ClientSocket, RequestInfo.IOBuffer, … … 303 299 RequestInfo.ThreadNum) != 0) 304 300 return GH_ERROR; 305 if ((NextLine[0] == ' ') || (NextLine[0] == '\t')) 306 strcat(CurLine, NextLine); 307 } while ((NextLine[0] == ' ') || (NextLine[0] == '\t')); 301 if ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t')) { 302 CurLine += NextLine; 303 } 304 } while ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t')); 308 305 309 Start = 0; 310 GetWord(FieldNameStr, CurLine, Start, End); 311 CharUpper(FieldNameStr); 306 GetWord(FieldNameStr, CurLine.begin(), CurLine.end(), next); 307 uc(FieldNameStr); 312 308 313 Len = strlen(CurLine) - End; 314 memcpy(FieldValStr, CurLine + End, Len); 315 FieldValStr[Len] = 0; 309 FieldValStr = substr(next, CurLine.end()); 316 310 317 311 //Process it … … 319 313 //All constants are in canonized, thus in upper case and case sensitive 320 314 //comparisons are used 315 321 316 //--Just About Always-- 322 if (strcmp("ACCEPT:", FieldNameStr) == 0) { 323 if (RequestFields.AcceptStr[0] == '\0') { 324 strncpy(RequestFields.AcceptStr, FieldValStr, ReqAcceptStrLen - 1); 325 } 326 else { 327 //Append it with a comma 328 int AcceptStrLen = strlen(RequestFields.AcceptStr); 329 if ((ReqAcceptStrLen - AcceptStrLen) >= 10) { 330 strncat(RequestFields.AcceptStr, ", ", ReqAcceptStrLen - AcceptStrLen - 1); 331 strncat(RequestFields.AcceptStr, FieldValStr, ReqAcceptStrLen - AcceptStrLen - 3); 332 } 333 } 334 } 335 else if (strcmp("DATE:", FieldNameStr) == 0) { 336 strncpy(RequestFields.DateStr, FieldValStr, ReqDateStrLen - 1); 337 } 338 else if (strcmp("USER-AGENT:", FieldNameStr) == 0) { 339 strncpy(RequestFields.UserAgentStr, FieldValStr, ReqUserAgentStrLen - 1); 340 } 341 else if (strcmp("CONNECTION:", FieldNameStr) == 0) { 342 strncpy(RequestFields.ConnectionStr, FieldValStr, ReqConnectionStrLen - 1); 317 if (FieldNameStr == "ACCEPT:") { 318 if (!RequestFields.AcceptStr.empty()) { 319 RequestFields.AcceptStr += ", "; 320 } 321 RequestFields.AcceptStr += FieldValStr; 322 } 323 else if (FieldNameStr == "DATE:") { 324 RequestFields.DateStr = FieldValStr; 325 } 326 else if (FieldNameStr == "USER-AGENT:") { 327 RequestFields.UserAgentStr = FieldValStr; 328 } 329 else if (FieldNameStr == "CONNECTION:") { 330 RequestFields.ConnectionStr = FieldValStr; 343 331 } 344 332 //--Sometimes-- 345 else if ( strcmp("ACCEPT-LANGUAGE:", FieldNameStr) == 0) {346 strncpy(RequestFields.AcceptLangStr, FieldValStr, ReqAcceptLangStrLen - 1);347 } 348 else if ( strcmp("REFERER:", FieldNameStr) == 0) {349 strncpy(RequestFields.RefererStr, FieldValStr, ReqRefererStrLen - 1);350 } 351 else if ( strcmp("IF-MODIFIED-SINCE:", FieldNameStr) == 0) {352 strncpy(RequestFields.IfModSinceStr, FieldValStr, ReqIfModSinceStrLen - 1);333 else if (FieldNameStr == "ACCEPT-LANGUAGE:") { 334 RequestFields.AcceptLangStr = FieldValStr; 335 } 336 else if (FieldNameStr == "REFERER:") { 337 RequestFields.RefererStr = FieldValStr; 338 } 339 else if (FieldNameStr == "IF-MODIFIED-SINCE:") { 340 RequestFields.IfModSinceStr = FieldValStr; 353 341 } 354 342 //--Uncommon-- 355 else if ( strcmp("FROM:", FieldNameStr) == 0) {356 strncpy(RequestFields.FromStr, FieldValStr, ReqFromStrLen - 1);357 } 358 else if ( strcmp("MIME-VERSION:", FieldNameStr) == 0) {359 strncpy(RequestFields.MIMEVerStr, FieldValStr, ReqMIMEVerStrLen - 1);360 } 361 else if ( strcmp("PRAGMA:", FieldNameStr) == 0) {362 strncpy(RequestFields.PragmaStr, FieldValStr, ReqPragmaStrLen - 1);343 else if (FieldNameStr == "FROM:") { 344 RequestFields.FromStr = FieldValStr; 345 } 346 else if (FieldNameStr == "MIME-VERSION:") { 347 RequestFields.MIMEVerStr = FieldValStr; 348 } 349 else if (FieldNameStr == "PRAGMA:") { 350 RequestFields.PragmaStr = FieldValStr; 363 351 } 364 352 //--Special case-- 365 else if ( strcmp("AUTHORIZATION:", FieldNameStr) == 0) {366 strncpy(RequestFields.AuthorizationStr, FieldValStr, ReqAuthorizationStrLen - 1);367 } 368 else if ( strcmp("CONTENT-LENGTH:", FieldNameStr) == 0) {369 strncpy(RequestFields.ContentLengthStr, FieldValStr, ReqContentLengthStrLen - 1);370 } 371 else if ( strcmp("CONTENT-TYPE:", FieldNameStr) == 0) {372 strncpy(RequestFields.ContentTypeStr, FieldValStr, ReqContentTypeStrLen - 1);373 } 374 else if ( strcmp("CONTENT-ENCODING:", FieldNameStr) == 0) {375 strncpy(RequestFields.ContentEncodingStr, FieldValStr, ReqContentEncodingStrLen - 1);376 } 377 else {353 else if (FieldNameStr == "AUTHORIZATION:") { 354 RequestFields.AuthorizationStr = FieldValStr; 355 } 356 else if (FieldNameStr == "CONTENT-LENGTH:") { 357 RequestFields.ContentLengthStr = FieldValStr; 358 } 359 else if (FieldNameStr == "CONTENT-TYPE:") { 360 RequestFields.ContentTypeStr = FieldValStr; 361 } 362 else if (FieldNameStr == "CONTENT-ENCODING:") { 363 RequestFields.ContentEncodingStr = FieldValStr; 364 } 365 else if (!FieldNameStr.empty()) { 378 366 //Add it to the other headers 379 int VarLen = strlen(FieldNameStr); 380 if (FieldNameStr[VarLen - 1] == ':') { 381 //Remove the colon 382 FieldNameStr[VarLen - 1] = '\0'; 383 VarLen--; 384 } 385 RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Var = new char[VarLen + 1]; 386 RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Val = new char[Len + 1]; 387 strcpy(RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Var, FieldNameStr); 388 strcpy(RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Val, FieldValStr); 367 368 //Remove the colon 369 if (*(FieldNameStr.end()-1) == ':') { 370 FieldNameStr.pop_back(); 371 } 372 RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Var = FieldNameStr; 373 RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Val = FieldValStr; 389 374 RequestFields.NumOtherHeaders++; 390 375 } 391 strcpy(CurLine, NextLine);392 } 393 394 if ( RequestFields.ContentLengthStr[0] != 0) { //Do we have attached data?376 CurLine = NextLine; 377 } 378 379 if (!RequestFields.ContentLengthStr.empty()) { //Do we have attached data? 395 380 unsigned int NumRecv; 396 381 397 RequestFields.ContentLength = atol(RequestFields.ContentLengthStr);382 RequestFields.ContentLength = RequestFields.ContentLengthStr.getint(); 398 383 if (RequestFields.ContentLength > 0) { 399 384 … … 447 432 void CleanUpHTTPHeaders(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields) { 448 433 //Clean up memory allocated for the Content 449 if (RequestFields.Content != NULL) 434 if (RequestFields.Content != NULL) { 450 435 delete[] RequestFields.Content; 451 while (RequestFields.NumOtherHeaders > 0) {452 RequestFields.NumOtherHeaders--;453 delete[] RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Var;454 delete[] RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Val;455 436 } 456 437 -
trunk/gsdl/src/w32server/httpreq.h
r2286 r3810 29 29 #define HTTPREQ_H 30 30 31 // need this to avoid bizarre compiler problems under VC++ 6.0 32 #if !defined (GSDL_NAMESPACE_BROKEN) && !defined (GSDL_USE_IOS_H) 33 # include <iostream> 34 # include <fstream> 35 using namespace std; 36 #endif 37 31 38 #include "locate.h" 32 39 #include "text_t.h" … … 50 57 51 58 //Length constants for RequestFieldsT 52 #define ReqMethodStrLen 2453 #define ReqVersionStrLen 2454 #define ReqDateStrLen 4855 #define ReqMIMEVerStrLen 2456 #define ReqPragmaStrLen 12857 #define ReqAuthorizationStrLen 51258 #define ReqFromStrLen 12859 #define ReqIfModSinceStrLen 4860 #define ReqRefererStrLen 51261 #define ReqUserAgentStrLen 25662 #define ReqContentEncodingStrLen 12863 #define ReqContentTypeStrLen 12864 #define ReqContentLengthStrLen 4865 #define ReqAcceptStrLen 25666 #define ReqAcceptLangStrLen 4867 #define ReqConnectionStrLen 2468 59 #define ReqAuthorizedUserStrLen 48 69 60 #define ReqPathInfoStrLen 512 … … 74 65 75 66 struct RequestHeaderT { 76 char *Var;77 char *Val;67 text_t Var; 68 text_t Val; 78 69 }; 79 70 80 71 struct RequestFieldsT { 81 72 //Simple request line info v0.9 82 char MethodStr[ReqMethodStrLen];73 text_t MethodStr; 83 74 text_t URIStr; 84 75 //added v1.0 85 char VersionStr[ReqVersionStrLen];76 text_t VersionStr; 86 77 //General Header 87 char DateStr[ReqDateStrLen];88 char MIMEVerStr[ReqMIMEVerStrLen];89 char PragmaStr[ReqPragmaStrLen];78 text_t DateStr; 79 text_t MIMEVerStr; 80 text_t PragmaStr; 90 81 //Request Header 91 char AuthorizationStr[ReqAuthorizationStrLen];92 char FromStr[ReqFromStrLen];93 char IfModSinceStr[ReqIfModSinceStrLen];94 char RefererStr[ReqRefererStrLen];95 char UserAgentStr[ReqUserAgentStrLen];82 text_t AuthorizationStr; 83 text_t FromStr; 84 text_t IfModSinceStr; 85 text_t RefererStr; 86 text_t UserAgentStr; 96 87 //Entity Header (Only CGI stuff) 97 char ContentEncodingStr[ReqContentEncodingStrLen];98 char ContentTypeStr[ReqContentTypeStrLen];99 char ContentLengthStr[ReqContentLengthStrLen];88 text_t ContentEncodingStr; 89 text_t ContentTypeStr; 90 text_t ContentLengthStr; 100 91 //v1.0 Optional (the more common ones) 101 char AcceptStr[ReqAcceptStrLen];102 char AcceptLangStr[ReqAcceptLangStrLen];92 text_t AcceptStr; 93 text_t AcceptLangStr; 103 94 //v1.1 Exentions 104 char ConnectionStr[ReqConnectionStrLen];95 text_t ConnectionStr; 105 96 //Pointer to buffer containing the content 106 97 DWORD ContentLength; -
trunk/gsdl/src/w32server/netio.cpp
r2353 r3810 333 333 } 334 334 335 int GetLine( char *OutStr, SOCKET ClientSocket, BYTE *IOBuffer, int IOBufferSize,335 int GetLine(text_t &OutStr, SOCKET ClientSocket, BYTE *IOBuffer, int IOBufferSize, 336 336 int &BufferIndex, int &DataInBuffer, int ThreadNum) { 337 338 int i;337 338 OutStr.clear(); 339 339 char CurChar; 340 340 341 i = 0;342 341 do { 343 342 if (BufferIndex == DataInBuffer) { //Need more data … … 352 351 BufferIndex++; 353 352 if ((CurChar != 10) && (CurChar != 13)) { 354 OutStr[i] = CurChar; 355 i++; 356 } 357 } while ((CurChar != 10) && (i < NETIO_MAX_LINE)); 358 if (i == NETIO_MAX_LINE) { 359 return -1; 360 } 361 362 OutStr[i] = 0; 353 OutStr.push_back(CurChar); 354 } 355 } while (CurChar != 10); 356 363 357 return 0; 364 358 } -
trunk/gsdl/src/w32server/netio.h
r2286 r3810 26 26 *********************************************************************/ 27 27 28 #include "text_t.h" 29 28 30 /* 29 31 Module Name: Net IO … … 48 50 SendFile 49 51 */ 50 51 //Public definitions52 //Max line size for GetLine53 #define NETIO_MAX_LINE 30054 52 55 53 //Public Functions … … 131 129 just changes an index. Also has the ability to do multi-threaded debuging 132 130 Parameters: 133 OutStr - Varible were output is put (a length of NETIO_MAX_LINE is assumed)131 OutStr - Varible were output is put 134 132 ClientSocket - The socket to get data from 135 133 IOBuffer - A pointer to a chunk of memory to put data in … … 141 139 Returns: -1 on disconnect or error (abort connection), 0 on success 142 140 */ 143 int GetLine( char *OutStr, SOCKET ClientSocket, BYTE *IOBuffer, int IOBufferSize,141 int GetLine(text_t &OutStr, SOCKET ClientSocket, BYTE *IOBuffer, int IOBufferSize, 144 142 int &BufferIndex, int &DataInBuffer, int ThreadNum); 145 143 -
trunk/gsdl/src/w32server/parse.cpp
r2286 r3810 84 84 } 85 85 /******************************************************************************/ 86 void GetWord(char *DestStr, const char *SourceStr, const int Start, int &End) { 87 int i, Len; 88 89 Len = 0; 90 i = Start; 91 while ((SourceStr[i] != ' ') && (SourceStr[i] != '\t') && (SourceStr[i] != 0)) { 92 Len++; 93 i++; 94 } 95 //Create the substring 96 memcpy(DestStr, SourceStr + Start, Len); 97 DestStr[Len] = 0; 98 //Set End 99 while ((SourceStr[i] != 0) && 100 ((SourceStr[i] == ' ') || (SourceStr[i] == '\t'))) { 101 i ++; 102 } 103 End = i; 104 } 105 /******************************************************************************/ 106 void GetLastWord(char *DestString, const char *SourceStr, int &Start) { 107 int SourceLen, i, Len; 108 109 Len = 0; 110 SourceLen = strlen(SourceStr); 111 i = SourceLen - 1; 112 while ((i >= 0) && (SourceStr[i] != ' ') && (SourceStr[i] != '\t')) { 113 Len++; 114 i--; 115 } 116 //Create the substring 117 memcpy(DestString, SourceStr + SourceLen - Len, Len); 118 DestString[Len] = 0; 119 Start = i + 1; 86 void GetWord(text_t &DestStr, text_t::const_iterator first, 87 text_t::const_iterator last, text_t::const_iterator &next) { 88 89 DestStr.clear(); 90 next = last; 91 92 while (first != last) { 93 if (*first == ' ' || *first == '\t') { 94 first++; 95 while ((first != last) && ((*first == ' ') || (*first == '\t'))) { 96 first++; 97 } 98 next = first; 99 break; 100 } else { 101 DestStr.push_back(*first); 102 } 103 first++; 104 } 105 } 106 /******************************************************************************/ 107 108 void GetLastWord(text_t &DestStr, text_t::const_iterator first, text_t::const_iterator last, 109 text_t::const_iterator &Start) { 110 111 DestStr.clear(); 112 Start = first; 113 114 while (first != last) { 115 if ((*first == ' ') || (*first == '\t')) { 116 DestStr.clear(); 117 Start = first+1; 118 } else { 119 DestStr.push_back(*first); 120 } 121 first ++; 122 } 120 123 } 121 124 /******************************************************************************/ -
trunk/gsdl/src/w32server/parse.h
r2286 r3810 25 25 * 26 26 *********************************************************************/ 27 28 #include "text_t.h" 27 29 28 30 /* … … 96 98 /* 97 99 Function Name: GetWord 98 Purpose: Gets leftmost substring without a space, starts at any position at 99 the start string and sets End to be the next non-space charactor in the 100 string. ' ' and '\t' and considered spaces 100 Purpose: Gets leftmost substring without a space in the string between the iterators 101 'here' and 'end'. Sets 'DestStr' to the substring. Sets the 'next' iterator 102 to the next non-space charactor in the string. ' ' and '\t' and considered 103 spaces 101 104 Parameters: 102 105 DestString - Destination buffer for substring 103 SourceString - Source string to make substing from 104 Start - 0 based string index to start at 105 End - At end of function call is set to the location of next non-space 106 charactor 107 108 Notes: If Start is greater than strlen(SourceStr) then a memory error may 109 occur. 106 first - First character in source string 107 last - end iterator (one past last character) of source string 108 next - At end of function call is set to the location of next non-space 109 charactor in source string 110 110 */ 111 void GetWord( char *DestStr, const char *SourceStr,112 const int Start, int &End);111 void GetWord(text_t &DestStr, text_t::const_iterator first, 112 text_t::const_iterator last, text_t::const_iterator &next); 113 113 114 114 /* 115 115 Function Name: GetLastWord 116 Purpose: Gets rightmost substring without a space sets Start to be the 0 based117 index of where the substring startsin the original string.116 Purpose: Gets rightmost substring without a space sets Start to be the first 117 character of the substring in the original string. 118 118 Parameters: 119 119 DestString - Destination buffer for substring 120 SourceString- Source string to make substing from121 Start - 0 based string index where the DestString starts at120 first and last - Source string to make substing from 121 Start - where the DestString starts at in the source string 122 122 */ 123 void GetLastWord(char *DestString, const char *SourceStr, int &Start); 123 void GetLastWord(text_t &DestStr, text_t::const_iterator first, text_t::const_iterator last, 124 text_t::const_iterator &Start); 124 125 125 126
Note:
See TracChangeset
for help on using the changeset viewer.