00001
00002
00003
00004
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
00031
00032
00033 #include "config.h"
00034
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037
00038 #if HAVE_UNISTD_H
00039 #include <unistd.h>
00040 #endif
00041
00042 #include <cstdio>
00043 #include <cerrno>
00044 #include <cstring>
00045 #include <cstdlib>
00046 #include <sstream>
00047 #include <iostream>
00048
00049 using std::istringstream ;
00050 using std::cout ;
00051 using std::endl ;
00052
00053 #include "BESUtil.h"
00054 #include "BESForbiddenError.h"
00055 #include "BESNotFoundError.h"
00056 #include "BESInternalError.h"
00057
00058 #define CRLF "\r\n"
00059
00064 void
00065 BESUtil::set_mime_text( ostream &strm )
00066 {
00067 strm << "HTTP/1.0 200 OK" << CRLF ;
00068 strm << "XBES-Server: " << PACKAGE_STRING << CRLF ;
00069
00070 const time_t t = time(0);
00071 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00072 strm << "Last-Modified: " << rfc822_date(t).c_str() << CRLF ;
00073
00074 strm << "Content-Type: text/plain" << CRLF ;
00075
00076 strm << "Content-Description: unknown" << CRLF ;
00077 strm << CRLF ;
00078 }
00079
00084 void
00085 BESUtil::set_mime_html( ostream &strm )
00086 {
00087 strm << "HTTP/1.0 200 OK" << CRLF ;
00088 strm << "XBES-Server: " << PACKAGE_STRING << CRLF ;
00089
00090 const time_t t = time(0);
00091 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00092 strm << "Last-Modified: " << rfc822_date(t).c_str() << CRLF ;
00093
00094 strm << "Content-type: text/html" << CRLF ;
00095
00096 strm << "Content-Description: unknown" << CRLF ;
00097 strm << CRLF ;
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static const char *days[]={"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
00133 static const char *months[]={"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
00134 "Aug", "Sep", "Oct", "Nov", "Dec"};
00135
00145 string
00146 BESUtil::rfc822_date(const time_t t)
00147 {
00148 struct tm *stm = gmtime(&t);
00149 char d[256];
00150
00151 snprintf(d, 255, "%s, %02d %s %4d %02d:%02d:%02d GMT", days[stm->tm_wday],
00152 stm->tm_mday, months[stm->tm_mon],
00153 1900 + stm->tm_year,
00154 stm->tm_hour, stm->tm_min, stm->tm_sec);
00155 d[255] = '\0';
00156 return string(d);
00157 }
00158
00159 string
00160 BESUtil::unhexstring( string s )
00161 {
00162 int val;
00163 istringstream ss( s ) ;
00164 ss >> std::hex >> val;
00165 char tmp_str[2];
00166 tmp_str[0] = static_cast<char>(val);
00167 tmp_str[1] = '\0';
00168 return string(tmp_str);
00169 }
00170
00171
00172
00173 string
00174 BESUtil::www2id(const string &in, const string &escape, const string &except)
00175 {
00176 string::size_type i = 0;
00177 string res = in;
00178 while ((i = res.find_first_of(escape, i)) != string::npos) {
00179 if (except.find(res.substr(i, 3)) != string::npos) {
00180 i += 3;
00181 continue;
00182 }
00183 res.replace(i, 3, unhexstring(res.substr(i + 1, 2)));
00184 }
00185
00186 return res;
00187 }
00188
00189 string
00190 BESUtil::lowercase( const string &s )
00191 {
00192 string return_string = s ;
00193 for( int j = 0; j < static_cast<int>(return_string.length()); j++ )
00194 {
00195 return_string[j] = (char)tolower( return_string[j] ) ;
00196 }
00197
00198 return return_string ;
00199 }
00200
00201 string
00202 BESUtil::unescape( const string &s )
00203 {
00204 bool done = false ;
00205 string::size_type index = 0 ;
00206
00207 string new_str ;
00208 while( !done )
00209 {
00210 string::size_type bs = s.find( '\\', index ) ;
00211 if( bs == string::npos )
00212 {
00213 new_str += s.substr( index, s.length() - index ) ;
00214 done = true ;
00215 }
00216 else
00217 {
00218 new_str += s.substr( index, bs - index ) ;
00219 new_str += s[bs+1] ;
00220 index = bs+2 ;
00221 }
00222 }
00223
00224 return new_str ;
00225 }
00226
00248 void
00249 BESUtil::check_path( const string &path,
00250 const string &root,
00251 bool follow_sym_links )
00252 {
00253
00254
00255 if( path == "" )
00256 return ;
00257
00258
00259
00260 string::size_type dotdot = path.find( ".." ) ;
00261 if( dotdot != string::npos )
00262 {
00263 string s = (string)"You are not allowed to access the node " + path;
00264 throw BESForbiddenError( s, __FILE__, __LINE__ ) ;
00265 }
00266
00267
00268
00269
00270 bool done = false ;
00271
00272
00273 string rem = path ;
00274 if( rem[0] == '/' )
00275 rem = rem.substr( 1, rem.length() - 1 ) ;
00276 if( rem[rem.length()-1] == '/' )
00277 rem = rem.substr( 0, rem.length() - 1 ) ;
00278
00279
00280 string fullpath = root ;
00281 if( fullpath[fullpath.length()-1] == '/' )
00282 {
00283 fullpath = fullpath.substr( 0, fullpath.length() - 1 ) ;
00284 }
00285
00286
00287 string checked ;
00288
00289 while( !done )
00290 {
00291 size_t slash = rem.find( '/' ) ;
00292 if( slash == string::npos )
00293 {
00294 fullpath = fullpath + "/" + rem ;
00295 checked = checked + "/" + rem ;
00296 done = true ;
00297 }
00298 else
00299 {
00300 fullpath = fullpath + "/" + rem.substr( 0, slash ) ;
00301 checked = checked + "/" + rem.substr( 0, slash ) ;
00302 rem = rem.substr( slash + 1, rem.length() - slash ) ;
00303 }
00304
00305 if( !follow_sym_links )
00306 {
00307 struct stat buf;
00308 int statret = lstat( fullpath.c_str(), &buf ) ;
00309 if( statret == -1 )
00310 {
00311 int errsv = errno ;
00312
00313
00314 char *s_err = strerror( errsv ) ;
00315 string error = "Unable to access node " + checked + ": " ;
00316 if( s_err )
00317 {
00318 error = error + s_err ;
00319 }
00320 else
00321 {
00322 error = error + "unknow access error" ;
00323 }
00324
00325
00326 if( errsv == ENOENT )
00327 {
00328 throw BESNotFoundError( error, __FILE__, __LINE__ ) ;
00329 }
00330 else
00331 {
00332 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00333 }
00334 }
00335 else
00336 {
00337
00338 if( S_ISLNK( buf.st_mode ) )
00339 {
00340 string error = "You do not have permission to access "
00341 + checked ;
00342 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00343 }
00344 }
00345 }
00346 else
00347 {
00348
00349
00350 struct stat buf ;
00351 int statret = stat( fullpath.c_str(), &buf ) ;
00352 if( statret == -1 )
00353 {
00354 int errsv = errno ;
00355
00356
00357 char *s_err = strerror( errsv ) ;
00358 string error = "Unable to access node " + checked + ": " ;
00359 if( s_err )
00360 {
00361 error = error + s_err ;
00362 }
00363 else
00364 {
00365 error = error + "unknow access error" ;
00366 }
00367
00368
00369 if( errsv == ENOENT )
00370 {
00371 throw BESNotFoundError( error, __FILE__, __LINE__ ) ;
00372 }
00373 else
00374 {
00375 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00376 }
00377 }
00378 }
00379 }
00380 }
00381
00382 char *
00383 BESUtil::fastpidconverter( char *buf, int base )
00384 {
00385 return fastpidconverter( getpid(), buf, base ) ;
00386 }
00387
00388 char *
00389 BESUtil::fastpidconverter(
00390 long val,
00391 char *buf,
00392 int base)
00393 {
00394 ldiv_t r;
00395
00396 if (base > 36 || base < 2)
00397 {
00398 *buf = '\0';
00399 return buf;
00400 }
00401 if (val < 0)
00402 *buf++ = '-';
00403 r = ldiv (labs(val), base);
00404
00405
00406
00407 if (r.quot > 0)
00408 buf = fastpidconverter ( r.quot, buf, base);
00409
00410
00411 *buf++ = "0123456789abcdefghijklmnopqrstuvwxyz"[(int)r.rem];
00412 *buf = '\0';
00413 return buf;
00414 }
00415
00416 void
00417 BESUtil::removeLeadingAndTrailingBlanks( string &key )
00418 {
00419 if( !key.empty() )
00420 {
00421 string::size_type first = key.find_first_not_of( " \t\n\r" ) ;
00422 string::size_type last = key.find_last_not_of( " \t\n\r" ) ;
00423 if( first == string::npos ) key = "" ;
00424 else
00425 {
00426 string::size_type num = last - first + 1 ;
00427 string new_key = key.substr( first, num ) ;
00428 key = new_key ;
00429 }
00430 }
00431 }
00432
00433 string
00434 BESUtil::entity( char c )
00435 {
00436 switch( c )
00437 {
00438 case '>': return ">";
00439 case '<': return "<";
00440 case '&': return "&";
00441 case '\'': return "'";
00442 case '\"': return """;
00443 default: return string(1,c);
00444 }
00445 }
00446
00453 string
00454 BESUtil::id2xml( string in, const string ¬_allowed )
00455 {
00456 string::size_type i = 0 ;
00457
00458 while( ( i = in.find_first_of( not_allowed, i ) ) != string::npos )
00459 {
00460 in.replace( i, 1, entity( in[i] ) ) ;
00461 i++ ;
00462 }
00463
00464 return in ;
00465 }
00466
00472 string
00473 BESUtil::xml2id(string in)
00474 {
00475 string::size_type i = 0;
00476
00477 while ((i = in.find(">", i)) != string::npos)
00478 in.replace(i, 4, ">");
00479
00480 i = 0;
00481 while ((i = in.find("<", i)) != string::npos)
00482 in.replace(i, 4, "<");
00483
00484 i = 0;
00485 while ((i = in.find("&", i)) != string::npos)
00486 in.replace(i, 5, "&");
00487
00488 i = 0;
00489 while ((i = in.find("'", i)) != string::npos)
00490 in.replace(i, 6, "'");
00491
00492 i = 0;
00493 while ((i = in.find(""", i)) != string::npos)
00494 in.replace(i, 6, "\"");
00495
00496 return in;
00497 }
00498
00512 void
00513 BESUtil::explode( char delim, const string &str, list<string> &values )
00514 {
00515 std::string::size_type start = 0 ;
00516 std::string::size_type qstart = 0 ;
00517 std::string::size_type adelim = 0 ;
00518 std::string::size_type aquote = 0 ;
00519 bool done = false ;
00520 while( !done )
00521 {
00522 string aval ;
00523 if( str[start] == '"' )
00524 {
00525 bool endquote = false ;
00526 qstart = start+1 ;
00527 while( !endquote )
00528 {
00529 aquote = str.find( '"', qstart ) ;
00530 if( aquote == string::npos )
00531 {
00532 string currval = str.substr( start, str.length() - start ) ;
00533 string err = "BESUtil::explode - No end quote after value "
00534 + currval ;
00535 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00536 }
00537
00538
00539 if( str[aquote-1] == '\\' )
00540 {
00541 if( str[aquote-2] == '\\' )
00542 {
00543 endquote = true ;
00544 qstart = aquote + 1 ;
00545 }
00546 else
00547 {
00548 qstart = aquote+1 ;
00549 }
00550 }
00551 else
00552 {
00553 endquote = true ;
00554 qstart = aquote + 1 ;
00555 }
00556 }
00557 if( str[qstart] != delim && qstart != str.length() )
00558 {
00559 string currval = str.substr( start, qstart - start ) ;
00560 string err = "BESUtil::explode - No delim after end quote "
00561 + currval ;
00562 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00563 }
00564 if( qstart == str.length() )
00565 {
00566 adelim = string::npos ;
00567 }
00568 else
00569 {
00570 adelim = qstart ;
00571 }
00572 }
00573 else
00574 {
00575 adelim = str.find( delim, start ) ;
00576 }
00577 if( adelim == string::npos )
00578 {
00579 aval = str.substr( start, str.length() - start ) ;
00580 done = true ;
00581 }
00582 else
00583 {
00584 aval = str.substr( start, adelim - start ) ;
00585 }
00586 values.push_back( aval ) ;
00587 start = adelim + 1 ;
00588 if( start == str.length() )
00589 {
00590 done = true ;
00591 }
00592 }
00593 }
00594
00605 string
00606 BESUtil::implode( const list<string> &values, char delim )
00607 {
00608 string result ;
00609 list<string>::const_iterator i = values.begin() ;
00610 list<string>::const_iterator e = values.end() ;
00611 bool first = true ;
00612 string::size_type d;
00613 for( ; i != e; i++ )
00614 {
00615 if( !first ) result += delim ;
00616 d = (*i).find( delim ) ;
00617 if( d != string::npos && (*i)[0] != '"' )
00618 {
00619 string err = (string)"BESUtil::implode - delimiter exists in value "
00620 + (*i) ;
00621 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00622 }
00623
00624 result += (*i) ;
00625 first = false ;
00626 }
00627 return result ;
00628 }
00629