Mercurial > hg > orthanc-wsi
comparison Framework/Orthanc/Core/Toolbox.cpp @ 43:9621fd6f17c9
sync
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 09 Nov 2016 17:34:20 +0100 |
parents | 5f4e367f7b0d |
children | 06847108819c |
comparison
equal
deleted
inserted
replaced
42:ee25d35663ac | 43:9621fd6f17c9 |
---|---|
34 #include "Toolbox.h" | 34 #include "Toolbox.h" |
35 | 35 |
36 #include "OrthancException.h" | 36 #include "OrthancException.h" |
37 #include "Logging.h" | 37 #include "Logging.h" |
38 | 38 |
39 #include <boost/algorithm/string/replace.hpp> | |
40 #include <boost/lexical_cast.hpp> | |
41 #include <boost/locale.hpp> | |
42 #include <boost/uuid/sha1.hpp> | |
43 | |
39 #include <string> | 44 #include <string> |
40 #include <stdint.h> | 45 #include <stdint.h> |
41 #include <string.h> | 46 #include <string.h> |
42 #include <boost/filesystem.hpp> | |
43 #include <boost/filesystem/fstream.hpp> | |
44 #include <boost/uuid/sha1.hpp> | |
45 #include <boost/lexical_cast.hpp> | |
46 #include <algorithm> | 47 #include <algorithm> |
47 #include <ctype.h> | 48 #include <ctype.h> |
48 | 49 |
49 #if BOOST_HAS_DATE_TIME == 1 | 50 #if BOOST_HAS_REGEX == 1 |
50 #include <boost/date_time/posix_time/posix_time.hpp> | 51 # include <boost/regex.hpp> |
51 #endif | 52 #endif |
52 | 53 |
53 #if BOOST_HAS_REGEX == 1 | 54 #if BOOST_HAS_LOCALE != 1 |
54 #include <boost/regex.hpp> | 55 # error Since version 0.7.6, Orthanc entirely relies on boost::locale |
55 #endif | 56 #endif |
56 | |
57 #if defined(_WIN32) | |
58 #include <windows.h> | |
59 #include <process.h> // For "_spawnvp()" and "_getpid()" | |
60 #else | |
61 #include <unistd.h> // For "execvp()" | |
62 #include <sys/wait.h> // For "waitpid()" | |
63 #endif | |
64 | |
65 #if defined(__APPLE__) && defined(__MACH__) | |
66 #include <mach-o/dyld.h> /* _NSGetExecutablePath */ | |
67 #include <limits.h> /* PATH_MAX */ | |
68 #endif | |
69 | |
70 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) | |
71 #include <limits.h> /* PATH_MAX */ | |
72 #include <signal.h> | |
73 #include <unistd.h> | |
74 #endif | |
75 | |
76 #if BOOST_HAS_LOCALE != 1 | |
77 #error Since version 0.7.6, Orthanc entirely relies on boost::locale | |
78 #endif | |
79 | |
80 #include <boost/locale.hpp> | |
81 | |
82 | 57 |
83 #if ORTHANC_ENABLE_MD5 == 1 | 58 #if ORTHANC_ENABLE_MD5 == 1 |
84 # include "../Resources/ThirdParty/md5/md5.h" | 59 # include "../Resources/ThirdParty/md5/md5.h" |
85 #endif | 60 #endif |
86 | |
87 | 61 |
88 #if ORTHANC_ENABLE_BASE64 == 1 | 62 #if ORTHANC_ENABLE_BASE64 == 1 |
89 # include "../Resources/ThirdParty/base64/base64.h" | 63 # include "../Resources/ThirdParty/base64/base64.h" |
90 #endif | 64 #endif |
91 | 65 |
101 } | 75 } |
102 } | 76 } |
103 #endif | 77 #endif |
104 | 78 |
105 | 79 |
80 | |
81 // Inclusions for UUID | |
82 // http://stackoverflow.com/a/1626302 | |
83 | |
84 extern "C" | |
85 { | |
86 #ifdef WIN32 | |
87 # include <rpc.h> | |
88 #else | |
89 # include <uuid/uuid.h> | |
90 #endif | |
91 } | |
92 | |
93 | |
106 #if ORTHANC_ENABLE_PUGIXML == 1 | 94 #if ORTHANC_ENABLE_PUGIXML == 1 |
107 #include "ChunkedBuffer.h" | 95 # include "ChunkedBuffer.h" |
108 #include <pugixml.hpp> | 96 # include <pugixml.hpp> |
109 #endif | 97 #endif |
110 | 98 |
111 | 99 |
112 namespace Orthanc | 100 namespace Orthanc |
113 { | 101 { |
121 #error Support your platform here | 109 #error Support your platform here |
122 #endif | 110 #endif |
123 } | 111 } |
124 | 112 |
125 | 113 |
126 #if ORTHANC_SANDBOXED == 0 | |
127 static bool finish_; | |
128 static ServerBarrierEvent barrierEvent_; | |
129 | |
130 #if defined(_WIN32) | |
131 static BOOL WINAPI ConsoleControlHandler(DWORD dwCtrlType) | |
132 { | |
133 // http://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx | |
134 finish_ = true; | |
135 return true; | |
136 } | |
137 #else | |
138 static void SignalHandler(int signal) | |
139 { | |
140 if (signal == SIGHUP) | |
141 { | |
142 barrierEvent_ = ServerBarrierEvent_Reload; | |
143 } | |
144 | |
145 finish_ = true; | |
146 } | |
147 #endif | |
148 | |
149 | |
150 static ServerBarrierEvent ServerBarrierInternal(const bool* stopFlag) | |
151 { | |
152 #if defined(_WIN32) | |
153 SetConsoleCtrlHandler(ConsoleControlHandler, true); | |
154 #else | |
155 signal(SIGINT, SignalHandler); | |
156 signal(SIGQUIT, SignalHandler); | |
157 signal(SIGTERM, SignalHandler); | |
158 signal(SIGHUP, SignalHandler); | |
159 #endif | |
160 | |
161 // Active loop that awakens every 100ms | |
162 finish_ = false; | |
163 barrierEvent_ = ServerBarrierEvent_Stop; | |
164 while (!(*stopFlag || finish_)) | |
165 { | |
166 Toolbox::USleep(100 * 1000); | |
167 } | |
168 | |
169 #if defined(_WIN32) | |
170 SetConsoleCtrlHandler(ConsoleControlHandler, false); | |
171 #else | |
172 signal(SIGINT, NULL); | |
173 signal(SIGQUIT, NULL); | |
174 signal(SIGTERM, NULL); | |
175 signal(SIGHUP, NULL); | |
176 #endif | |
177 | |
178 return barrierEvent_; | |
179 } | |
180 | |
181 | |
182 ServerBarrierEvent Toolbox::ServerBarrier(const bool& stopFlag) | |
183 { | |
184 return ServerBarrierInternal(&stopFlag); | |
185 } | |
186 | |
187 ServerBarrierEvent Toolbox::ServerBarrier() | |
188 { | |
189 const bool stopFlag = false; | |
190 return ServerBarrierInternal(&stopFlag); | |
191 } | |
192 #endif /* ORTHANC_SANDBOXED */ | |
193 | |
194 | |
195 void Toolbox::ToUpperCase(std::string& s) | 114 void Toolbox::ToUpperCase(std::string& s) |
196 { | 115 { |
197 std::transform(s.begin(), s.end(), s.begin(), toupper); | 116 std::transform(s.begin(), s.end(), s.begin(), toupper); |
198 } | 117 } |
199 | 118 |
215 const std::string& source) | 134 const std::string& source) |
216 { | 135 { |
217 result = source; | 136 result = source; |
218 ToLowerCase(result); | 137 ToLowerCase(result); |
219 } | 138 } |
220 | |
221 | |
222 static std::streamsize GetStreamSize(std::istream& f) | |
223 { | |
224 // http://www.cplusplus.com/reference/iostream/istream/tellg/ | |
225 f.seekg(0, std::ios::end); | |
226 std::streamsize size = f.tellg(); | |
227 f.seekg(0, std::ios::beg); | |
228 | |
229 return size; | |
230 } | |
231 | |
232 | |
233 #if ORTHANC_SANDBOXED == 0 | |
234 void Toolbox::ReadFile(std::string& content, | |
235 const std::string& path) | |
236 { | |
237 if (!IsRegularFile(path)) | |
238 { | |
239 LOG(ERROR) << std::string("The path does not point to a regular file: ") << path; | |
240 throw OrthancException(ErrorCode_RegularFileExpected); | |
241 } | |
242 | |
243 boost::filesystem::ifstream f; | |
244 f.open(path, std::ifstream::in | std::ifstream::binary); | |
245 if (!f.good()) | |
246 { | |
247 throw OrthancException(ErrorCode_InexistentFile); | |
248 } | |
249 | |
250 std::streamsize size = GetStreamSize(f); | |
251 content.resize(size); | |
252 if (size != 0) | |
253 { | |
254 f.read(reinterpret_cast<char*>(&content[0]), size); | |
255 } | |
256 | |
257 f.close(); | |
258 } | |
259 #endif | |
260 | |
261 | |
262 #if ORTHANC_SANDBOXED == 0 | |
263 bool Toolbox::ReadHeader(std::string& header, | |
264 const std::string& path, | |
265 size_t headerSize) | |
266 { | |
267 if (!IsRegularFile(path)) | |
268 { | |
269 LOG(ERROR) << std::string("The path does not point to a regular file: ") << path; | |
270 throw OrthancException(ErrorCode_RegularFileExpected); | |
271 } | |
272 | |
273 boost::filesystem::ifstream f; | |
274 f.open(path, std::ifstream::in | std::ifstream::binary); | |
275 if (!f.good()) | |
276 { | |
277 throw OrthancException(ErrorCode_InexistentFile); | |
278 } | |
279 | |
280 bool full = true; | |
281 | |
282 { | |
283 std::streamsize size = GetStreamSize(f); | |
284 if (size <= 0) | |
285 { | |
286 headerSize = 0; | |
287 full = false; | |
288 } | |
289 else if (static_cast<size_t>(size) < headerSize) | |
290 { | |
291 headerSize = size; // Truncate to the size of the file | |
292 full = false; | |
293 } | |
294 } | |
295 | |
296 header.resize(headerSize); | |
297 if (headerSize != 0) | |
298 { | |
299 f.read(reinterpret_cast<char*>(&header[0]), headerSize); | |
300 } | |
301 | |
302 f.close(); | |
303 | |
304 return full; | |
305 } | |
306 #endif | |
307 | |
308 | |
309 #if ORTHANC_SANDBOXED == 0 | |
310 void Toolbox::WriteFile(const void* content, | |
311 size_t size, | |
312 const std::string& path) | |
313 { | |
314 boost::filesystem::ofstream f; | |
315 f.open(path, std::ofstream::out | std::ofstream::binary); | |
316 if (!f.good()) | |
317 { | |
318 throw OrthancException(ErrorCode_CannotWriteFile); | |
319 } | |
320 | |
321 if (size != 0) | |
322 { | |
323 f.write(reinterpret_cast<const char*>(content), size); | |
324 | |
325 if (!f.good()) | |
326 { | |
327 f.close(); | |
328 throw OrthancException(ErrorCode_FileStorageCannotWrite); | |
329 } | |
330 } | |
331 | |
332 f.close(); | |
333 } | |
334 #endif | |
335 | |
336 | |
337 #if ORTHANC_SANDBOXED == 0 | |
338 void Toolbox::WriteFile(const std::string& content, | |
339 const std::string& path) | |
340 { | |
341 WriteFile(content.size() > 0 ? content.c_str() : NULL, | |
342 content.size(), path); | |
343 } | |
344 #endif | |
345 | |
346 | |
347 #if ORTHANC_SANDBOXED == 0 | |
348 void Toolbox::RemoveFile(const std::string& path) | |
349 { | |
350 if (boost::filesystem::exists(path)) | |
351 { | |
352 if (IsRegularFile(path)) | |
353 { | |
354 boost::filesystem::remove(path); | |
355 } | |
356 else | |
357 { | |
358 throw OrthancException(ErrorCode_RegularFileExpected); | |
359 } | |
360 } | |
361 } | |
362 #endif | |
363 | 139 |
364 | 140 |
365 void Toolbox::SplitUriComponents(UriComponents& components, | 141 void Toolbox::SplitUriComponents(UriComponents& components, |
366 const std::string& uri) | 142 const std::string& uri) |
367 { | 143 { |
527 return r; | 303 return r; |
528 } | 304 } |
529 } | 305 } |
530 | 306 |
531 | 307 |
532 | |
533 #if ORTHANC_SANDBOXED == 0 | |
534 uint64_t Toolbox::GetFileSize(const std::string& path) | |
535 { | |
536 try | |
537 { | |
538 return static_cast<uint64_t>(boost::filesystem::file_size(path)); | |
539 } | |
540 catch (boost::filesystem::filesystem_error&) | |
541 { | |
542 throw OrthancException(ErrorCode_InexistentFile); | |
543 } | |
544 } | |
545 #endif | |
546 | |
547 | |
548 #if ORTHANC_ENABLE_MD5 == 1 | 308 #if ORTHANC_ENABLE_MD5 == 1 |
549 static char GetHexadecimalCharacter(uint8_t value) | 309 static char GetHexadecimalCharacter(uint8_t value) |
550 { | 310 { |
551 assert(value < 16); | 311 assert(value < 16); |
552 | 312 |
656 const std::string& content) | 416 const std::string& content) |
657 { | 417 { |
658 result = "data:" + mime + ";base64," + base64_encode(content); | 418 result = "data:" + mime + ";base64," + base64_encode(content); |
659 } | 419 } |
660 | 420 |
661 #endif | |
662 | |
663 | |
664 | |
665 #if defined(_WIN32) | |
666 static std::string GetPathToExecutableInternal() | |
667 { | |
668 // Yes, this is ugly, but there is no simple way to get the | |
669 // required buffer size, so we use a big constant | |
670 std::vector<char> buffer(32768); | |
671 /*int bytes =*/ GetModuleFileNameA(NULL, &buffer[0], static_cast<DWORD>(buffer.size() - 1)); | |
672 return std::string(&buffer[0]); | |
673 } | |
674 | |
675 #elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) | |
676 static std::string GetPathToExecutableInternal() | |
677 { | |
678 std::vector<char> buffer(PATH_MAX + 1); | |
679 ssize_t bytes = readlink("/proc/self/exe", &buffer[0], buffer.size() - 1); | |
680 if (bytes == 0) | |
681 { | |
682 throw OrthancException(ErrorCode_PathToExecutable); | |
683 } | |
684 | |
685 return std::string(&buffer[0]); | |
686 } | |
687 | |
688 #elif defined(__APPLE__) && defined(__MACH__) | |
689 static std::string GetPathToExecutableInternal() | |
690 { | |
691 char pathbuf[PATH_MAX + 1]; | |
692 unsigned int bufsize = static_cast<int>(sizeof(pathbuf)); | |
693 | |
694 _NSGetExecutablePath( pathbuf, &bufsize); | |
695 | |
696 return std::string(pathbuf); | |
697 } | |
698 | |
699 #elif ORTHANC_SANDBOXED == 1 | |
700 // Sandboxed Orthanc, no access to the executable | |
701 | |
702 #else | |
703 #error Support your platform here | |
704 #endif | |
705 | |
706 | |
707 #if ORTHANC_SANDBOXED == 0 | |
708 std::string Toolbox::GetPathToExecutable() | |
709 { | |
710 boost::filesystem::path p(GetPathToExecutableInternal()); | |
711 return boost::filesystem::absolute(p).string(); | |
712 } | |
713 | |
714 | |
715 std::string Toolbox::GetDirectoryOfExecutable() | |
716 { | |
717 boost::filesystem::path p(GetPathToExecutableInternal()); | |
718 return boost::filesystem::absolute(p.parent_path()).string(); | |
719 } | |
720 #endif | 421 #endif |
721 | 422 |
722 | 423 |
723 static const char* GetBoostLocaleEncoding(const Encoding sourceEncoding) | 424 static const char* GetBoostLocaleEncoding(const Encoding sourceEncoding) |
724 { | 425 { |
993 else | 694 else |
994 { | 695 { |
995 return IsSHA1(s.c_str(), s.size()); | 696 return IsSHA1(s.c_str(), s.size()); |
996 } | 697 } |
997 } | 698 } |
998 | |
999 | |
1000 #if BOOST_HAS_DATE_TIME == 1 | |
1001 std::string Toolbox::GetNowIsoString() | |
1002 { | |
1003 boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); | |
1004 return boost::posix_time::to_iso_string(now); | |
1005 } | |
1006 | |
1007 void Toolbox::GetNowDicom(std::string& date, | |
1008 std::string& time) | |
1009 { | |
1010 boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); | |
1011 tm tm = boost::posix_time::to_tm(now); | |
1012 | |
1013 char s[32]; | |
1014 sprintf(s, "%04d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | |
1015 date.assign(s); | |
1016 | |
1017 // TODO milliseconds | |
1018 sprintf(s, "%02d%02d%02d.%06d", tm.tm_hour, tm.tm_min, tm.tm_sec, 0); | |
1019 time.assign(s); | |
1020 } | |
1021 #endif | |
1022 | 699 |
1023 | 700 |
1024 std::string Toolbox::StripSpaces(const std::string& source) | 701 std::string Toolbox::StripSpaces(const std::string& source) |
1025 { | 702 { |
1026 size_t first = 0; | 703 size_t first = 0; |
1176 | 853 |
1177 result.push_back(currentItem); | 854 result.push_back(currentItem); |
1178 } | 855 } |
1179 | 856 |
1180 | 857 |
1181 #if ORTHANC_SANDBOXED == 0 | |
1182 void Toolbox::MakeDirectory(const std::string& path) | |
1183 { | |
1184 if (boost::filesystem::exists(path)) | |
1185 { | |
1186 if (!boost::filesystem::is_directory(path)) | |
1187 { | |
1188 throw OrthancException(ErrorCode_DirectoryOverFile); | |
1189 } | |
1190 } | |
1191 else | |
1192 { | |
1193 if (!boost::filesystem::create_directories(path)) | |
1194 { | |
1195 throw OrthancException(ErrorCode_MakeDirectory); | |
1196 } | |
1197 } | |
1198 } | |
1199 #endif | |
1200 | |
1201 | |
1202 #if ORTHANC_SANDBOXED == 0 | |
1203 bool Toolbox::IsExistingFile(const std::string& path) | |
1204 { | |
1205 return boost::filesystem::exists(path); | |
1206 } | |
1207 #endif | |
1208 | |
1209 | |
1210 #if ORTHANC_ENABLE_PUGIXML == 1 | 858 #if ORTHANC_ENABLE_PUGIXML == 1 |
1211 class ChunkedBufferWriter : public pugi::xml_writer | 859 class ChunkedBufferWriter : public pugi::xml_writer |
1212 { | 860 { |
1213 private: | 861 private: |
1214 ChunkedBuffer buffer_; | 862 ChunkedBuffer buffer_; |
1326 writer.Flatten(target); | 974 writer.Flatten(target); |
1327 } | 975 } |
1328 | 976 |
1329 #endif | 977 #endif |
1330 | 978 |
1331 | |
1332 #if ORTHANC_SANDBOXED == 0 | |
1333 void Toolbox::ExecuteSystemCommand(const std::string& command, | |
1334 const std::vector<std::string>& arguments) | |
1335 { | |
1336 // Convert the arguments as a C array | |
1337 std::vector<char*> args(arguments.size() + 2); | |
1338 | |
1339 args.front() = const_cast<char*>(command.c_str()); | |
1340 | |
1341 for (size_t i = 0; i < arguments.size(); i++) | |
1342 { | |
1343 args[i + 1] = const_cast<char*>(arguments[i].c_str()); | |
1344 } | |
1345 | |
1346 args.back() = NULL; | |
1347 | |
1348 int status; | |
1349 | |
1350 #if defined(_WIN32) | |
1351 // http://msdn.microsoft.com/en-us/library/275khfab.aspx | |
1352 status = static_cast<int>(_spawnvp(_P_OVERLAY, command.c_str(), &args[0])); | |
1353 | |
1354 #else | |
1355 int pid = fork(); | |
1356 | |
1357 if (pid == -1) | |
1358 { | |
1359 // Error in fork() | |
1360 #if ORTHANC_ENABLE_LOGGING == 1 | |
1361 LOG(ERROR) << "Cannot fork a child process"; | |
1362 #endif | |
1363 | |
1364 throw OrthancException(ErrorCode_SystemCommand); | |
1365 } | |
1366 else if (pid == 0) | |
1367 { | |
1368 // Execute the system command in the child process | |
1369 execvp(command.c_str(), &args[0]); | |
1370 | |
1371 // We should never get here | |
1372 _exit(1); | |
1373 } | |
1374 else | |
1375 { | |
1376 // Wait for the system command to exit | |
1377 waitpid(pid, &status, 0); | |
1378 } | |
1379 #endif | |
1380 | |
1381 if (status != 0) | |
1382 { | |
1383 #if ORTHANC_ENABLE_LOGGING == 1 | |
1384 LOG(ERROR) << "System command failed with status code " << status; | |
1385 #endif | |
1386 | |
1387 throw OrthancException(ErrorCode_SystemCommand); | |
1388 } | |
1389 } | |
1390 #endif | |
1391 | 979 |
1392 | 980 |
1393 bool Toolbox::IsInteger(const std::string& str) | 981 bool Toolbox::IsInteger(const std::string& str) |
1394 { | 982 { |
1395 std::string s = StripSpaces(str); | 983 std::string s = StripSpaces(str); |
1494 else | 1082 else |
1495 { | 1083 { |
1496 return str.compare(0, prefix.size(), prefix) == 0; | 1084 return str.compare(0, prefix.size(), prefix) == 0; |
1497 } | 1085 } |
1498 } | 1086 } |
1499 | |
1500 | |
1501 #if ORTHANC_SANDBOXED == 0 | |
1502 int Toolbox::GetProcessId() | |
1503 { | |
1504 #if defined(_WIN32) | |
1505 return static_cast<int>(_getpid()); | |
1506 #else | |
1507 return static_cast<int>(getpid()); | |
1508 #endif | |
1509 } | |
1510 #endif | |
1511 | |
1512 | |
1513 #if ORTHANC_SANDBOXED == 0 | |
1514 bool Toolbox::IsRegularFile(const std::string& path) | |
1515 { | |
1516 namespace fs = boost::filesystem; | |
1517 | |
1518 try | |
1519 { | |
1520 if (fs::exists(path)) | |
1521 { | |
1522 fs::file_status status = fs::status(path); | |
1523 return (status.type() == boost::filesystem::regular_file || | |
1524 status.type() == boost::filesystem::reparse_file); // Fix BitBucket issue #11 | |
1525 } | |
1526 } | |
1527 catch (fs::filesystem_error&) | |
1528 { | |
1529 } | |
1530 | |
1531 return false; | |
1532 } | |
1533 #endif | |
1534 | |
1535 | |
1536 FILE* Toolbox::OpenFile(const std::string& path, | |
1537 FileMode mode) | |
1538 { | |
1539 #if defined(_WIN32) | |
1540 // TODO Deal with special characters by converting to the current locale | |
1541 #endif | |
1542 | |
1543 const char* m; | |
1544 switch (mode) | |
1545 { | |
1546 case FileMode_ReadBinary: | |
1547 m = "rb"; | |
1548 break; | |
1549 | |
1550 case FileMode_WriteBinary: | |
1551 m = "wb"; | |
1552 break; | |
1553 | |
1554 default: | |
1555 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1556 } | |
1557 | |
1558 return fopen(path.c_str(), m); | |
1559 } | |
1560 | |
1561 | 1087 |
1562 | 1088 |
1563 static bool IsUnreservedCharacter(char c) | 1089 static bool IsUnreservedCharacter(char c) |
1564 { | 1090 { |
1565 // This function checks whether "c" is an unserved character | 1091 // This function checks whether "c" is an unserved character |
1696 else | 1222 else |
1697 { | 1223 { |
1698 return static_cast<unsigned int>(v); | 1224 return static_cast<unsigned int>(v); |
1699 } | 1225 } |
1700 } | 1226 } |
1227 | |
1228 | |
1229 std::string Toolbox::GenerateUuid() | |
1230 { | |
1231 #ifdef WIN32 | |
1232 UUID uuid; | |
1233 UuidCreate ( &uuid ); | |
1234 | |
1235 unsigned char * str; | |
1236 UuidToStringA ( &uuid, &str ); | |
1237 | |
1238 std::string s( ( char* ) str ); | |
1239 | |
1240 RpcStringFreeA ( &str ); | |
1241 #else | |
1242 uuid_t uuid; | |
1243 uuid_generate_random ( uuid ); | |
1244 char s[37]; | |
1245 uuid_unparse ( uuid, s ); | |
1246 #endif | |
1247 return s; | |
1248 } | |
1249 | |
1250 | |
1251 bool Toolbox::IsUuid(const std::string& str) | |
1252 { | |
1253 if (str.size() != 36) | |
1254 { | |
1255 return false; | |
1256 } | |
1257 | |
1258 for (size_t i = 0; i < str.length(); i++) | |
1259 { | |
1260 if (i == 8 || i == 13 || i == 18 || i == 23) | |
1261 { | |
1262 if (str[i] != '-') | |
1263 return false; | |
1264 } | |
1265 else | |
1266 { | |
1267 if (!isalnum(str[i])) | |
1268 return false; | |
1269 } | |
1270 } | |
1271 | |
1272 return true; | |
1273 } | |
1274 | |
1275 | |
1276 bool Toolbox::StartsWithUuid(const std::string& str) | |
1277 { | |
1278 if (str.size() < 36) | |
1279 { | |
1280 return false; | |
1281 } | |
1282 | |
1283 if (str.size() == 36) | |
1284 { | |
1285 return IsUuid(str); | |
1286 } | |
1287 | |
1288 assert(str.size() > 36); | |
1289 if (!isspace(str[36])) | |
1290 { | |
1291 return false; | |
1292 } | |
1293 | |
1294 return IsUuid(str.substr(0, 36)); | |
1295 } | |
1701 } | 1296 } |