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
00034
00035
00036 #include "config.h"
00037
00038 static char rcsid[] not_used =
00039 {"$Id: util.cc 21699 2009-11-05 00:06:01Z jimg $"
00040 };
00041
00042 #include <cassert>
00043 #include <cstring>
00044
00045 #include <ctype.h>
00046 #ifndef TM_IN_SYS_TIME
00047 #include <time.h>
00048 #else
00049 #include <sys/time.h>
00050 #endif
00051
00052 #ifndef WIN32
00053 #include <unistd.h>
00054 #else
00055 #include <io.h>
00056 #include <fcntl.h>
00057 #include <process.h>
00058 #endif
00059
00060 #include <sys/types.h>
00061 #include <sys/stat.h>
00062
00063 #include <string>
00064 #include <sstream>
00065 #include <vector>
00066 #include <algorithm>
00067 #include <stdexcept>
00068
00069 #include "BaseType.h"
00070 #include "Str.h"
00071 #include "Url.h"
00072 #include "Sequence.h"
00073 #include "Error.h"
00074 #include "parser.h"
00075 #include "util.h"
00076 #include "GNURegex.h"
00077 #include "debug.h"
00078
00079
00080 using namespace std;
00081
00082 namespace libdap {
00083
00084
00085
00086
00095 string
00096 prune_spaces(const string &name)
00097 {
00098
00099 if (name.find_first_of(' ') == name.npos)
00100 return name;
00101 else {
00102
00103 unsigned int i = name.find_first_not_of(' ');
00104 string tmp_name = name.substr(i);
00105
00106
00107 unsigned int j = tmp_name.find('?') + 1;
00108 i = tmp_name.find_first_not_of(' ', j);
00109 tmp_name.erase(j, i - j);
00110
00111 return tmp_name;
00112 }
00113 }
00114
00115
00116
00117
00118 bool
00119 unique_names(vector<BaseType *> l, const string &var_name,
00120 const string &type_name, string &msg)
00121 {
00122
00123 vector<string> names(l.size());
00124
00125 int nelem = 0;
00126 typedef std::vector<BaseType *>::const_iterator citer ;
00127 for (citer i = l.begin(); i != l.end(); i++) {
00128 assert(*i);
00129 names[nelem++] = (*i)->name();
00130 DBG(cerr << "NAMES[" << nelem - 1 << "]=" << names[nelem-1] << endl);
00131 }
00132
00133
00134 sort(names.begin(), names.end());
00135
00136 #ifdef DODS_DEBUG2
00137 cout << "unique:" << endl;
00138 for (int ii = 0; ii < nelem; ++ii)
00139 cout << "NAMES[" << ii << "]=" << names[ii] << endl;
00140 #endif
00141
00142
00143 sort(names.begin(), names.end());
00144
00145 #ifdef DODS_DEBUG2
00146 cout << "unique:" << endl;
00147 for (int ii = 0; ii < nelem; ++ii)
00148 cout << "NAMES[" << ii << "]=" << names[ii] << endl;
00149 #endif
00150
00151
00152 for (int j = 1; j < nelem; ++j) {
00153 if (names[j-1] == names[j]) {
00154 ostringstream oss;
00155 oss << "The variable `" << names[j]
00156 << "' is used more than once in " << type_name << " `"
00157 << var_name << "'";
00158 msg = oss.str();
00159
00160 return false;
00161 }
00162 }
00163
00164 return true;
00165 }
00166
00167 const char *
00168 libdap_root()
00169 {
00170 return LIBDAP_ROOT;
00171 }
00172
00173 extern "C"
00174 const char *
00175 libdap_version()
00176 {
00177 return PACKAGE_VERSION;
00178 }
00179
00180 extern "C"
00181 const char *
00182 libdap_name()
00183 {
00184 return PACKAGE_NAME;
00185 }
00186
00187
00188
00189
00190
00191 #if COMPRESSION_FOR_SERVER3
00192
00193
00194
00195
00196
00197
00198
00199
00200 bool
00201 deflate_exists()
00202 {
00203 DBG(cerr << "Entering deflate_exists...");
00204
00205 int status = false;
00206 struct stat buf;
00207
00208 #ifdef WIN32
00209 string deflate = (string)libdap_root() + "\\bin\\deflate";
00210 #else
00211 string deflate = (string)libdap_root() + "/sbin/deflate";
00212 #endif
00213
00214
00215
00216
00217
00218
00219 status = (stat(deflate.c_str(), &buf) == 0)
00220 #ifdef WIN32
00221 || (stat(".\\deflate", &buf) == 0);
00222 #else
00223 || (stat("./deflate", &buf) == 0);
00224 #endif
00225
00226
00227 #ifdef WIN32
00228 status &= (buf.st_mode & _S_IEXEC);
00229 #else
00230 status &= buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH);
00231 #endif
00232 DBG(cerr << " returning " << (status ? "true." : "false.") << endl);
00233 return (status != 0);
00234 }
00235
00236 FILE *
00237 compressor(FILE *output, int &childpid)
00238 {
00239 #ifdef WIN32
00240
00241
00242
00243 int pid, data[2];
00244 int hStdIn, hStdOut;
00245
00246 if (_pipe(data, 512, O_BINARY | O_NOINHERIT) < 0) {
00247 cerr << "Could not create IPC channel for compressor process"
00248 << endl;
00249 return NULL;
00250 }
00251
00252
00253
00254
00255
00256
00257 hStdIn = _dup(_fileno(stdin));
00258 hStdOut = _dup(_fileno(stdout));
00259
00260
00261 if (_dup2(data[0], _fileno(stdin)) != 0) {
00262 cerr << "dup of child stdin failed" << endl;
00263 return NULL;
00264 }
00265
00266 if (_dup2(_fileno(output), _fileno(stdout)) != 0) {
00267 cerr << "dup of child stdout failed" << endl;
00268 return NULL;
00269 }
00270
00271
00272 string deflate = "deflate.exe";
00273 if ((pid = _spawnlp(_P_NOWAIT, deflate.c_str(), deflate.c_str(),
00274 "-c", "5", "-s", NULL)) < 0) {
00275 cerr << "Could not spawn to create compressor process" << endl;
00276 return NULL;
00277 }
00278
00279
00280 if (_dup2(hStdIn, _fileno(stdin)) != 0) {
00281 cerr << "dup of stdin failed" << endl;
00282 return NULL;
00283 }
00284 if (_dup2(hStdOut, _fileno(stdout)) != 0) {
00285 cerr << "dup of stdout failed" << endl;
00286 return NULL;
00287 }
00288 close(hStdIn);
00289 close(hStdOut);
00290
00291
00292
00293 close(data[0]);
00294 FILE *input = fdopen(data[1], "w");
00295 setbuf(input, 0);
00296 childpid = pid;
00297 return input;
00298
00299 #else
00300 FILE *ret_file = NULL ;
00301
00302 int pid, data[2];
00303
00304 if (pipe(data) < 0) {
00305 cerr << "Could not create IPC channel for compressor process"
00306 << endl;
00307 return NULL;
00308 }
00309
00310 if ((pid = fork()) < 0) {
00311 cerr << "Could not fork to create compressor process" << endl;
00312 return NULL;
00313 }
00314
00315
00316
00317
00318
00319 if (pid > 0) {
00320 close(data[0]);
00321 ret_file = fdopen(data[1], "w");
00322 setbuf(ret_file, 0);
00323 childpid = pid;
00324 }
00325 else {
00326 close(data[1]);
00327 dup2(data[0], 0);
00328 dup2(fileno(output), 1);
00329
00330 DBG(cerr << "Opening compression stream." << endl);
00331
00332
00333
00334
00335 string deflate = (string)libdap_root() + "/sbin/deflate";
00336 (void) execl(deflate.c_str(), "deflate", "-c", "5", "-s", NULL);
00337 (void) execl("./deflate", "deflate", "-c", "5", "-s", NULL);
00338 cerr << "Warning: Could not start compressor!" << endl;
00339 cerr << "defalte should be in DODS_ROOT/etc or in the CWD!"
00340 << endl;
00341 _exit(127);
00342 }
00343
00344 return ret_file ;
00345 #endif
00346 }
00347
00348 #endif // COMPRESSION_FOR_SERVER3
00349
00350
00351
00352
00353 string
00354 systime()
00355 {
00356 time_t TimBin;
00357
00358 if (time(&TimBin) == (time_t) - 1)
00359 return string("time() error");
00360 else {
00361 string TimStr = ctime(&TimBin);
00362 return TimStr.substr(0, TimStr.size() - 2);
00363 }
00364 }
00365
00366 void
00367 downcase(string &s)
00368 {
00369 for (unsigned int i = 0; i < s.length(); i++)
00370 s[i] = tolower(s[i]);
00371 }
00372
00373 bool
00374 is_quoted(const string &s)
00375 {
00376 return (!s.empty() && s[0] == '\"' && s[s.length()-1] == '\"');
00377 }
00378
00379 string
00380 remove_quotes(const string &s)
00381 {
00382 if (is_quoted(s))
00383 return s.substr(1, s.length() - 2);
00384 else
00385 return s;
00386 }
00387
00388 #ifdef WIN32
00389
00390
00391
00392
00393
00394 void flush_stream(iostream ios, FILE *out)
00395 {
00396 int nbytes;
00397 char buffer[512];
00398
00399 ios.get(buffer, 512, NULL);
00400 while ((nbytes = ios.gcount()) > 0) {
00401 fwrite(buffer, 1, nbytes, out);
00402 ios.get(buffer, 512, NULL);
00403 }
00404
00405 return;
00406 }
00407 #endif
00408
00409
00410 void
00411 append_long_to_string(long val, int base, string &str_val)
00412 {
00413
00414
00415
00416 char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00417
00418 ldiv_t r;
00419
00420 if (base > 36 || base < 2) {
00421
00422 std::invalid_argument ex("The parameter base has an invalid value.");
00423 throw ex;
00424 }
00425 if (val < 0)
00426 str_val += '-';
00427 r = ldiv(labs(val), base);
00428
00429
00430 if (r.quot > 0)
00431 append_long_to_string(r.quot, base, str_val);
00432
00433
00434
00435 str_val += digits[(int)r.rem];
00436 }
00437
00438
00439 string
00440 long_to_string(long val, int base)
00441 {
00442 string s;
00443 append_long_to_string(val, base, s);
00444 return s;
00445 }
00446
00447
00448 void append_double_to_string(const double &num, string &str)
00449 {
00450
00451
00452 ostringstream oss;
00453 oss.precision(9);
00454 oss << num;
00455 str += oss.str();
00456 }
00457
00458 string
00459 double_to_string(const double &num)
00460 {
00461 string s;
00462 append_double_to_string(num, s);
00463 return s;
00464 }
00465
00466
00467
00468
00469 string
00470 dap_version()
00471 {
00472 return (string)"OPeNDAP DAP/" + libdap_version() + ": compiled on " + __DATE__ + ":" + __TIME__ ;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481 #ifdef WIN32
00482 static const char path_sep[] =
00483 {"\\"
00484 };
00485 #else
00486 static const char path_sep[] =
00487 {"/"
00488 };
00489 #endif
00490
00491 string
00492 path_to_filename(string path)
00493 {
00494 string::size_type pos = path.rfind(path_sep);
00495
00496 return (pos == string::npos) ? path : path.substr(++pos);
00497 }
00498
00503 string
00504 file_to_string(FILE *fp)
00505 {
00506 rewind(fp);
00507 ostringstream oss;
00508 char c;
00509 while (fread(&c, 1, 1, fp))
00510 oss << c;
00511 return oss.str();
00512 }
00513
00516
00522 bool
00523 size_ok(unsigned int sz, unsigned int nelem)
00524 {
00525 return (sz > 0 && nelem < UINT_MAX / sz);
00526 }
00527
00544 bool
00545 pathname_ok(const string &path, bool strict)
00546 {
00547 if (path.length() > 255)
00548 return false;
00549
00550 Regex name("[-0-9A-z_./]+");
00551 if (!strict)
00552 name = "[:print:]+";
00553
00554 string::size_type len = path.length();
00555 int result = name.match(path.c_str(), len);
00556
00557
00558 if (len > INT_MAX || result != static_cast<int>(len))
00559 return false;
00560
00561 return true;
00562 }
00563
00565
00566 }
00567