cmCTestSubmitHandler.cxx 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc.
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmCTestSubmitHandler.h"
  11. #include "cmSystemTools.h"
  12. #include "cmVersion.h"
  13. #include "cmGeneratedFileStream.h"
  14. #include "cmCTest.h"
  15. #include <cmsys/Process.h>
  16. #include <cmsys/Base64.h>
  17. // For XML-RPC submission
  18. #include "cm_xmlrpc.h"
  19. // For curl submission
  20. #include "cm_curl.h"
  21. #include <sys/stat.h>
  22. #define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
  23. typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar;
  24. static size_t
  25. cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
  26. void *data)
  27. {
  28. register int realsize = (int)(size * nmemb);
  29. cmCTestSubmitHandlerVectorOfChar *vec
  30. = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
  31. const char* chPtr = static_cast<char*>(ptr);
  32. vec->insert(vec->end(), chPtr, chPtr + realsize);
  33. return realsize;
  34. }
  35. static size_t
  36. cmCTestSubmitHandlerCurlDebugCallback(CURL *, curl_infotype, char *chPtr,
  37. size_t size, void *data)
  38. {
  39. cmCTestSubmitHandlerVectorOfChar *vec
  40. = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
  41. vec->insert(vec->end(), chPtr, chPtr + size);
  42. return size;
  43. }
  44. //----------------------------------------------------------------------------
  45. cmCTestSubmitHandler::cmCTestSubmitHandler() : HTTPProxy(), FTPProxy()
  46. {
  47. this->Initialize();
  48. }
  49. //----------------------------------------------------------------------------
  50. void cmCTestSubmitHandler::Initialize()
  51. {
  52. // We submit all available parts by default.
  53. for(cmCTest::Part p = cmCTest::PartStart;
  54. p != cmCTest::PartCount; p = cmCTest::Part(p+1))
  55. {
  56. this->SubmitPart[p] = true;
  57. }
  58. this->CDash = false;
  59. this->HasWarnings = false;
  60. this->HasErrors = false;
  61. this->Superclass::Initialize();
  62. this->HTTPProxy = "";
  63. this->HTTPProxyType = 0;
  64. this->HTTPProxyAuth = "";
  65. this->FTPProxy = "";
  66. this->FTPProxyType = 0;
  67. this->LogFile = 0;
  68. this->Files.clear();
  69. }
  70. //----------------------------------------------------------------------------
  71. bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
  72. const std::set<cmStdString>& files,
  73. const cmStdString& remoteprefix,
  74. const cmStdString& url)
  75. {
  76. CURL *curl;
  77. CURLcode res;
  78. FILE* ftpfile;
  79. char error_buffer[1024];
  80. /* In windows, this will init the winsock stuff */
  81. ::curl_global_init(CURL_GLOBAL_ALL);
  82. cmCTest::SetOfStrings::const_iterator file;
  83. for ( file = files.begin(); file != files.end(); ++file )
  84. {
  85. /* get a curl handle */
  86. curl = curl_easy_init();
  87. if(curl)
  88. {
  89. // Using proxy
  90. if ( this->FTPProxyType > 0 )
  91. {
  92. curl_easy_setopt(curl, CURLOPT_PROXY, this->FTPProxy.c_str());
  93. switch (this->FTPProxyType)
  94. {
  95. case 2:
  96. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  97. break;
  98. case 3:
  99. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  100. break;
  101. default:
  102. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  103. }
  104. }
  105. // enable uploading
  106. ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
  107. // if there is little to no activity for too long stop submitting
  108. ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
  109. ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME,
  110. SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
  111. ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
  112. cmStdString local_file = *file;
  113. if ( !cmSystemTools::FileExists(local_file.c_str()) )
  114. {
  115. local_file = localprefix + "/" + *file;
  116. }
  117. cmStdString upload_as
  118. = url + "/" + remoteprefix + cmSystemTools::GetFilenameName(*file);
  119. struct stat st;
  120. if ( ::stat(local_file.c_str(), &st) )
  121. {
  122. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
  123. << local_file.c_str() << std::endl);
  124. ::curl_easy_cleanup(curl);
  125. ::curl_global_cleanup();
  126. return false;
  127. }
  128. ftpfile = ::fopen(local_file.c_str(), "rb");
  129. *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
  130. << upload_as.c_str() << std::endl;
  131. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
  132. << local_file.c_str() << " to "
  133. << upload_as.c_str() << std::endl);
  134. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  135. // specify target
  136. ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
  137. // now specify which file to upload
  138. ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
  139. // and give the size of the upload (optional)
  140. ::curl_easy_setopt(curl, CURLOPT_INFILESIZE,
  141. static_cast<long>(st.st_size));
  142. // and give curl the buffer for errors
  143. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  144. // specify handler for output
  145. ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  146. cmCTestSubmitHandlerWriteMemoryCallback);
  147. ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
  148. cmCTestSubmitHandlerCurlDebugCallback);
  149. /* we pass our 'chunk' struct to the callback function */
  150. cmCTestSubmitHandlerVectorOfChar chunk;
  151. cmCTestSubmitHandlerVectorOfChar chunkDebug;
  152. ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
  153. ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
  154. // Now run off and do what you've been told!
  155. res = ::curl_easy_perform(curl);
  156. if ( chunk.size() > 0 )
  157. {
  158. cmCTestLog(this->CTest, DEBUG, "CURL output: ["
  159. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  160. << std::endl);
  161. }
  162. if ( chunkDebug.size() > 0 )
  163. {
  164. cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
  165. << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
  166. << std::endl);
  167. }
  168. fclose(ftpfile);
  169. if ( res )
  170. {
  171. cmCTestLog(this->CTest, ERROR_MESSAGE,
  172. " Error when uploading file: "
  173. << local_file.c_str() << std::endl);
  174. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
  175. << error_buffer << std::endl);
  176. *this->LogFile << " Error when uploading file: "
  177. << local_file.c_str()
  178. << std::endl
  179. << " Error message was: "
  180. << error_buffer << std::endl
  181. << " Curl output was: ";
  182. // avoid dereference of empty vector
  183. if(chunk.size())
  184. {
  185. *this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size());
  186. cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
  187. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  188. << std::endl);
  189. }
  190. *this->LogFile << std::endl;
  191. ::curl_easy_cleanup(curl);
  192. ::curl_global_cleanup();
  193. return false;
  194. }
  195. // always cleanup
  196. ::curl_easy_cleanup(curl);
  197. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
  198. << std::endl);
  199. }
  200. }
  201. ::curl_global_cleanup();
  202. return true;
  203. }
  204. //----------------------------------------------------------------------------
  205. // Uploading files is simpler
  206. bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
  207. const std::set<cmStdString>& files,
  208. const cmStdString& remoteprefix,
  209. const cmStdString& url)
  210. {
  211. CURL *curl;
  212. CURLcode res;
  213. FILE* ftpfile;
  214. char error_buffer[1024];
  215. /* In windows, this will init the winsock stuff */
  216. ::curl_global_init(CURL_GLOBAL_ALL);
  217. cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
  218. cmStdString curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
  219. std::vector<std::string> args;
  220. cmSystemTools::ExpandListArgument(curlopt.c_str(), args);
  221. bool verifyPeerOff = false;
  222. bool verifyHostOff = false;
  223. for( std::vector<std::string>::iterator i = args.begin();
  224. i != args.end(); ++i)
  225. {
  226. if(*i == "CURLOPT_SSL_VERIFYPEER_OFF")
  227. {
  228. verifyPeerOff = true;
  229. }
  230. if(*i == "CURLOPT_SSL_VERIFYHOST_OFF")
  231. {
  232. verifyHostOff = true;
  233. }
  234. }
  235. cmStdString::size_type kk;
  236. cmCTest::SetOfStrings::const_iterator file;
  237. for ( file = files.begin(); file != files.end(); ++file )
  238. {
  239. /* get a curl handle */
  240. curl = curl_easy_init();
  241. if(curl)
  242. {
  243. if(verifyPeerOff)
  244. {
  245. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  246. " Set CURLOPT_SSL_VERIFYPEER to off\n");
  247. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
  248. }
  249. if(verifyHostOff)
  250. {
  251. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  252. " Set CURLOPT_SSL_VERIFYHOST to off\n");
  253. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
  254. }
  255. // Using proxy
  256. if ( this->HTTPProxyType > 0 )
  257. {
  258. curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
  259. switch (this->HTTPProxyType)
  260. {
  261. case 2:
  262. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  263. break;
  264. case 3:
  265. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  266. break;
  267. default:
  268. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  269. if (this->HTTPProxyAuth.size() > 0)
  270. {
  271. curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
  272. this->HTTPProxyAuth.c_str());
  273. }
  274. }
  275. }
  276. if(this->CTest->ShouldUseHTTP10())
  277. {
  278. curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  279. }
  280. // enable HTTP ERROR parsing
  281. curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
  282. /* enable uploading */
  283. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
  284. // if there is little to no activity for too long stop submitting
  285. ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
  286. ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME,
  287. SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
  288. /* HTTP PUT please */
  289. ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
  290. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  291. cmStdString local_file = *file;
  292. if ( !cmSystemTools::FileExists(local_file.c_str()) )
  293. {
  294. local_file = localprefix + "/" + *file;
  295. }
  296. cmStdString remote_file
  297. = remoteprefix + cmSystemTools::GetFilenameName(*file);
  298. *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
  299. << remote_file.c_str() << std::endl;
  300. cmStdString ofile = "";
  301. for ( kk = 0; kk < remote_file.size(); kk ++ )
  302. {
  303. char c = remote_file[kk];
  304. char hexCh[4] = { 0, 0, 0, 0 };
  305. hexCh[0] = c;
  306. switch ( c )
  307. {
  308. case '+':
  309. case '?':
  310. case '/':
  311. case '\\':
  312. case '&':
  313. case ' ':
  314. case '=':
  315. case '%':
  316. sprintf(hexCh, "%%%02X", (int)c);
  317. ofile.append(hexCh);
  318. break;
  319. default:
  320. ofile.append(hexCh);
  321. }
  322. }
  323. cmStdString upload_as
  324. = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
  325. + "FileName=" + ofile;
  326. struct stat st;
  327. if ( ::stat(local_file.c_str(), &st) )
  328. {
  329. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
  330. << local_file.c_str() << std::endl);
  331. ::curl_easy_cleanup(curl);
  332. ::curl_global_cleanup();
  333. return false;
  334. }
  335. ftpfile = ::fopen(local_file.c_str(), "rb");
  336. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
  337. << local_file.c_str() << " to "
  338. << upload_as.c_str() << " Size: " << st.st_size << std::endl);
  339. // specify target
  340. ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
  341. // now specify which file to upload
  342. ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
  343. // and give the size of the upload (optional)
  344. ::curl_easy_setopt(curl, CURLOPT_INFILESIZE,
  345. static_cast<long>(st.st_size));
  346. // and give curl the buffer for errors
  347. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  348. // specify handler for output
  349. ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  350. cmCTestSubmitHandlerWriteMemoryCallback);
  351. ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
  352. cmCTestSubmitHandlerCurlDebugCallback);
  353. /* we pass our 'chunk' struct to the callback function */
  354. cmCTestSubmitHandlerVectorOfChar chunk;
  355. cmCTestSubmitHandlerVectorOfChar chunkDebug;
  356. ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
  357. ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
  358. // Now run off and do what you've been told!
  359. res = ::curl_easy_perform(curl);
  360. if ( chunk.size() > 0 )
  361. {
  362. cmCTestLog(this->CTest, DEBUG, "CURL output: ["
  363. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  364. << std::endl);
  365. this->ParseResponse(chunk);
  366. }
  367. if ( chunkDebug.size() > 0 )
  368. {
  369. cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
  370. << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
  371. << std::endl);
  372. }
  373. fclose(ftpfile);
  374. if ( res )
  375. {
  376. cmCTestLog(this->CTest, ERROR_MESSAGE,
  377. " Error when uploading file: "
  378. << local_file.c_str() << std::endl);
  379. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
  380. << error_buffer << std::endl);
  381. *this->LogFile << " Error when uploading file: "
  382. << local_file.c_str()
  383. << std::endl
  384. << " Error message was: " << error_buffer
  385. << std::endl;
  386. // avoid deref of begin for zero size array
  387. if(chunk.size())
  388. {
  389. *this->LogFile << " Curl output was: "
  390. << cmCTestLogWrite(&*chunk.begin(), chunk.size())
  391. << std::endl;
  392. cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
  393. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  394. << std::endl);
  395. }
  396. ::curl_easy_cleanup(curl);
  397. ::curl_global_cleanup();
  398. return false;
  399. }
  400. // always cleanup
  401. ::curl_easy_cleanup(curl);
  402. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
  403. << std::endl);
  404. }
  405. }
  406. ::curl_global_cleanup();
  407. return true;
  408. }
  409. //----------------------------------------------------------------------------
  410. void cmCTestSubmitHandler
  411. ::ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk)
  412. {
  413. std::string output = "";
  414. for(cmCTestSubmitHandlerVectorOfChar::iterator i = chunk.begin();
  415. i != chunk.end(); ++i)
  416. {
  417. output += *i;
  418. }
  419. output = cmSystemTools::UpperCase(output);
  420. if(output.find("WARNING") != std::string::npos)
  421. {
  422. this->HasWarnings = true;
  423. }
  424. if(output.find("ERROR") != std::string::npos)
  425. {
  426. this->HasErrors = true;
  427. }
  428. if(this->HasWarnings || this->HasErrors)
  429. {
  430. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n" <<
  431. cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
  432. }
  433. }
  434. //----------------------------------------------------------------------------
  435. bool cmCTestSubmitHandler::TriggerUsingHTTP(
  436. const std::set<cmStdString>& files,
  437. const cmStdString& remoteprefix,
  438. const cmStdString& url)
  439. {
  440. CURL *curl;
  441. char error_buffer[1024];
  442. /* In windows, this will init the winsock stuff */
  443. ::curl_global_init(CURL_GLOBAL_ALL);
  444. cmCTest::SetOfStrings::const_iterator file;
  445. for ( file = files.begin(); file != files.end(); ++file )
  446. {
  447. /* get a curl handle */
  448. curl = curl_easy_init();
  449. if(curl)
  450. {
  451. // Using proxy
  452. if ( this->HTTPProxyType > 0 )
  453. {
  454. curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
  455. switch (this->HTTPProxyType)
  456. {
  457. case 2:
  458. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  459. break;
  460. case 3:
  461. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  462. break;
  463. default:
  464. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  465. if (this->HTTPProxyAuth.size() > 0)
  466. {
  467. curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
  468. this->HTTPProxyAuth.c_str());
  469. }
  470. }
  471. }
  472. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  473. // and give curl the buffer for errors
  474. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  475. // specify handler for output
  476. ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  477. cmCTestSubmitHandlerWriteMemoryCallback);
  478. ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
  479. cmCTestSubmitHandlerCurlDebugCallback);
  480. /* we pass our 'chunk' struct to the callback function */
  481. cmCTestSubmitHandlerVectorOfChar chunk;
  482. cmCTestSubmitHandlerVectorOfChar chunkDebug;
  483. ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
  484. ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
  485. cmStdString rfile
  486. = remoteprefix + cmSystemTools::GetFilenameName(*file);
  487. cmStdString ofile = "";
  488. cmStdString::iterator kk;
  489. for ( kk = rfile.begin(); kk < rfile.end(); ++ kk)
  490. {
  491. char c = *kk;
  492. char hexCh[4] = { 0, 0, 0, 0 };
  493. hexCh[0] = c;
  494. switch ( c )
  495. {
  496. case '+':
  497. case '?':
  498. case '/':
  499. case '\\':
  500. case '&':
  501. case ' ':
  502. case '=':
  503. case '%':
  504. sprintf(hexCh, "%%%02X", (int)c);
  505. ofile.append(hexCh);
  506. break;
  507. default:
  508. ofile.append(hexCh);
  509. }
  510. }
  511. cmStdString turl
  512. = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
  513. + "xmlfile=" + ofile;
  514. *this->LogFile << "Trigger url: " << turl.c_str() << std::endl;
  515. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Trigger url: "
  516. << turl.c_str() << std::endl);
  517. curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
  518. curl_easy_setopt(curl, CURLOPT_URL, turl.c_str());
  519. if ( curl_easy_perform(curl) )
  520. {
  521. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when triggering: "
  522. << turl.c_str() << std::endl);
  523. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
  524. << error_buffer << std::endl);
  525. *this->LogFile << "\tTrigerring failed with error: " << error_buffer
  526. << std::endl
  527. << " Error message was: " << error_buffer
  528. << std::endl;
  529. if(chunk.size())
  530. {
  531. *this->LogFile
  532. << " Curl output was: "
  533. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << std::endl;
  534. cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
  535. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  536. << std::endl);
  537. }
  538. ::curl_easy_cleanup(curl);
  539. ::curl_global_cleanup();
  540. return false;
  541. }
  542. if ( chunk.size() > 0 )
  543. {
  544. cmCTestLog(this->CTest, DEBUG, "CURL output: ["
  545. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  546. << std::endl);
  547. }
  548. if ( chunkDebug.size() > 0 )
  549. {
  550. cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
  551. << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size())
  552. << "]" << std::endl);
  553. }
  554. // always cleanup
  555. ::curl_easy_cleanup(curl);
  556. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
  557. }
  558. }
  559. ::curl_global_cleanup();
  560. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Dart server triggered..."
  561. << std::endl);
  562. return true;
  563. }
  564. //----------------------------------------------------------------------------
  565. bool cmCTestSubmitHandler::SubmitUsingSCP(
  566. const cmStdString& scp_command,
  567. const cmStdString& localprefix,
  568. const std::set<cmStdString>& files,
  569. const cmStdString& remoteprefix,
  570. const cmStdString& url)
  571. {
  572. if ( !scp_command.size() || !localprefix.size() ||
  573. !files.size() || !remoteprefix.size() || !url.size() )
  574. {
  575. return 0;
  576. }
  577. std::vector<const char*> argv;
  578. argv.push_back(scp_command.c_str()); // Scp command
  579. argv.push_back(scp_command.c_str()); // Dummy string for file
  580. argv.push_back(scp_command.c_str()); // Dummy string for remote url
  581. argv.push_back(0);
  582. cmsysProcess* cp = cmsysProcess_New();
  583. cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
  584. //cmsysProcess_SetTimeout(cp, timeout);
  585. int problems = 0;
  586. cmCTest::SetOfStrings::const_iterator file;
  587. for ( file = files.begin(); file != files.end(); ++file )
  588. {
  589. int retVal;
  590. std::string lfname = localprefix;
  591. cmSystemTools::ConvertToUnixSlashes(lfname);
  592. lfname += "/" + *file;
  593. lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
  594. argv[1] = lfname.c_str();
  595. std::string rfname = url + "/" + remoteprefix + *file;
  596. argv[2] = rfname.c_str();
  597. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \"" << argv[0]
  598. << "\" \"" << argv[1] << "\" \""
  599. << argv[2] << "\"" << std::endl);
  600. *this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
  601. << argv[2] << "\"" << std::endl;
  602. cmsysProcess_SetCommand(cp, &*argv.begin());
  603. cmsysProcess_Execute(cp);
  604. char* data;
  605. int length;
  606. while(cmsysProcess_WaitForData(cp, &data, &length, 0))
  607. {
  608. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  609. cmCTestLogWrite(data, length));
  610. }
  611. cmsysProcess_WaitForExit(cp, 0);
  612. int result = cmsysProcess_GetState(cp);
  613. if(result == cmsysProcess_State_Exited)
  614. {
  615. retVal = cmsysProcess_GetExitValue(cp);
  616. if ( retVal != 0 )
  617. {
  618. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "\tSCP returned: "
  619. << retVal << std::endl);
  620. *this->LogFile << "\tSCP returned: " << retVal << std::endl;
  621. problems ++;
  622. }
  623. }
  624. else if(result == cmsysProcess_State_Exception)
  625. {
  626. retVal = cmsysProcess_GetExitException(cp);
  627. cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
  628. << retVal << std::endl);
  629. *this->LogFile << "\tThere was an exception: " << retVal << std::endl;
  630. problems ++;
  631. }
  632. else if(result == cmsysProcess_State_Expired)
  633. {
  634. cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
  635. << std::endl);
  636. *this->LogFile << "\tThere was a timeout" << std::endl;
  637. problems ++;
  638. }
  639. else if(result == cmsysProcess_State_Error)
  640. {
  641. cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: "
  642. << cmsysProcess_GetErrorString(cp) << std::endl);
  643. *this->LogFile << "\tError executing SCP: "
  644. << cmsysProcess_GetErrorString(cp) << std::endl;
  645. problems ++;
  646. }
  647. }
  648. cmsysProcess_Delete(cp);
  649. if ( problems )
  650. {
  651. return false;
  652. }
  653. return true;
  654. }
  655. //----------------------------------------------------------------------------
  656. bool cmCTestSubmitHandler::SubmitUsingCP(
  657. const cmStdString& localprefix,
  658. const std::set<cmStdString>& files,
  659. const cmStdString& remoteprefix,
  660. const cmStdString& destination)
  661. {
  662. if ( !localprefix.size() ||
  663. !files.size() || !remoteprefix.size() || !destination.size() )
  664. {
  665. cmCTestLog(this->CTest, ERROR_MESSAGE,
  666. "Missing arguments for submit via cp:\n"
  667. << "\tlocalprefix: " << localprefix << "\n"
  668. << "\tNumber of files: " << files.size() << "\n"
  669. << "\tremoteprefix: " << remoteprefix << "\n"
  670. << "\tdestination: " << destination << std::endl);
  671. return 0;
  672. }
  673. cmCTest::SetOfStrings::const_iterator file;
  674. bool problems = false;
  675. for ( file = files.begin(); file != files.end(); ++file )
  676. {
  677. std::string lfname = localprefix;
  678. cmSystemTools::ConvertToUnixSlashes(lfname);
  679. lfname += "/" + *file;
  680. std::string rfname = destination + "/" + remoteprefix + *file;
  681. cmSystemTools::CopyFileAlways(lfname.c_str(), rfname.c_str());
  682. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Copy file: "
  683. << lfname.c_str() << " to "
  684. << rfname.c_str() << std::endl);
  685. }
  686. std::string tagDoneFile = destination + "/" + remoteprefix + "DONE";
  687. cmSystemTools::Touch(tagDoneFile.c_str(), true);
  688. if ( problems )
  689. {
  690. return false;
  691. }
  692. return true;
  693. }
  694. //----------------------------------------------------------------------------
  695. #if defined(CTEST_USE_XMLRPC)
  696. bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
  697. const std::set<cmStdString>& files,
  698. const cmStdString& remoteprefix,
  699. const cmStdString& url)
  700. {
  701. xmlrpc_env env;
  702. char ctestString[] = "CTest";
  703. std::string ctestVersionString = cmVersion::GetCMakeVersion();
  704. char* ctestVersion = const_cast<char*>(ctestVersionString.c_str());
  705. cmStdString realURL = url + "/" + remoteprefix + "/Command/";
  706. /* Start up our XML-RPC client library. */
  707. xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, ctestString, ctestVersion);
  708. /* Initialize our error-handling environment. */
  709. xmlrpc_env_init(&env);
  710. /* Call the famous server at UserLand. */
  711. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submitting to: "
  712. << realURL.c_str() << " (" << remoteprefix.c_str() << ")" << std::endl);
  713. cmCTest::SetOfStrings::const_iterator file;
  714. for ( file = files.begin(); file != files.end(); ++file )
  715. {
  716. xmlrpc_value *result;
  717. cmStdString local_file = *file;
  718. if ( !cmSystemTools::FileExists(local_file.c_str()) )
  719. {
  720. local_file = localprefix + "/" + *file;
  721. }
  722. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submit file: "
  723. << local_file.c_str() << std::endl);
  724. struct stat st;
  725. if ( ::stat(local_file.c_str(), &st) )
  726. {
  727. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
  728. << local_file.c_str() << std::endl);
  729. return false;
  730. }
  731. // off_t can be bigger than size_t. fread takes size_t.
  732. // make sure the file is not too big.
  733. if(static_cast<off_t>(static_cast<size_t>(st.st_size)) !=
  734. static_cast<off_t>(st.st_size))
  735. {
  736. cmCTestLog(this->CTest, ERROR_MESSAGE, " File too big: "
  737. << local_file.c_str() << std::endl);
  738. return false;
  739. }
  740. size_t fileSize = static_cast<size_t>(st.st_size);
  741. FILE* fp = fopen(local_file.c_str(), "rb");
  742. if ( !fp )
  743. {
  744. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot open file: "
  745. << local_file.c_str() << std::endl);
  746. return false;
  747. }
  748. unsigned char *fileBuffer = new unsigned char[fileSize];
  749. if ( fread(fileBuffer, 1, fileSize, fp) != fileSize )
  750. {
  751. delete [] fileBuffer;
  752. fclose(fp);
  753. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot read file: "
  754. << local_file.c_str() << std::endl);
  755. return false;
  756. }
  757. fclose(fp);
  758. char remoteCommand[] = "Submit.put";
  759. char* pRealURL = const_cast<char*>(realURL.c_str());
  760. result = xmlrpc_client_call(&env, pRealURL, remoteCommand,
  761. "(6)", fileBuffer, (xmlrpc_int32)fileSize );
  762. delete [] fileBuffer;
  763. if ( env.fault_occurred )
  764. {
  765. cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: "
  766. << env.fault_string << " (" << env.fault_code << ")" << std::endl);
  767. xmlrpc_env_clean(&env);
  768. xmlrpc_client_cleanup();
  769. return false;
  770. }
  771. /* Dispose of our result value. */
  772. xmlrpc_DECREF(result);
  773. }
  774. /* Clean up our error-handling environment. */
  775. xmlrpc_env_clean(&env);
  776. /* Shutdown our XML-RPC client library. */
  777. xmlrpc_client_cleanup();
  778. return true;
  779. }
  780. #else
  781. bool cmCTestSubmitHandler::SubmitUsingXMLRPC(cmStdString const&,
  782. std::set<cmStdString> const&,
  783. cmStdString const&,
  784. cmStdString const&)
  785. {
  786. return false;
  787. }
  788. #endif
  789. //----------------------------------------------------------------------------
  790. int cmCTestSubmitHandler::ProcessHandler()
  791. {
  792. std::string iscdash = this->CTest->GetCTestConfiguration("IsCDash");
  793. // cdash does not need to trigger so just return true
  794. if(iscdash.size())
  795. {
  796. this->CDash = true;
  797. }
  798. const std::string &buildDirectory
  799. = this->CTest->GetCTestConfiguration("BuildDirectory");
  800. if ( buildDirectory.size() == 0 )
  801. {
  802. cmCTestLog(this->CTest, ERROR_MESSAGE,
  803. "Cannot find BuildDirectory key in the DartConfiguration.tcl"
  804. << std::endl);
  805. return -1;
  806. }
  807. if ( getenv("HTTP_PROXY") )
  808. {
  809. this->HTTPProxyType = 1;
  810. this->HTTPProxy = getenv("HTTP_PROXY");
  811. if ( getenv("HTTP_PROXY_PORT") )
  812. {
  813. this->HTTPProxy += ":";
  814. this->HTTPProxy += getenv("HTTP_PROXY_PORT");
  815. }
  816. if ( getenv("HTTP_PROXY_TYPE") )
  817. {
  818. cmStdString type = getenv("HTTP_PROXY_TYPE");
  819. // HTTP/SOCKS4/SOCKS5
  820. if ( type == "HTTP" )
  821. {
  822. this->HTTPProxyType = 1;
  823. }
  824. else if ( type == "SOCKS4" )
  825. {
  826. this->HTTPProxyType = 2;
  827. }
  828. else if ( type == "SOCKS5" )
  829. {
  830. this->HTTPProxyType = 3;
  831. }
  832. }
  833. if ( getenv("HTTP_PROXY_USER") )
  834. {
  835. this->HTTPProxyAuth = getenv("HTTP_PROXY_USER");
  836. }
  837. if ( getenv("HTTP_PROXY_PASSWD") )
  838. {
  839. this->HTTPProxyAuth += ":";
  840. this->HTTPProxyAuth += getenv("HTTP_PROXY_PASSWD");
  841. }
  842. }
  843. if ( getenv("FTP_PROXY") )
  844. {
  845. this->FTPProxyType = 1;
  846. this->FTPProxy = getenv("FTP_PROXY");
  847. if ( getenv("FTP_PROXY_PORT") )
  848. {
  849. this->FTPProxy += ":";
  850. this->FTPProxy += getenv("FTP_PROXY_PORT");
  851. }
  852. if ( getenv("FTP_PROXY_TYPE") )
  853. {
  854. cmStdString type = getenv("FTP_PROXY_TYPE");
  855. // HTTP/SOCKS4/SOCKS5
  856. if ( type == "HTTP" )
  857. {
  858. this->FTPProxyType = 1;
  859. }
  860. else if ( type == "SOCKS4" )
  861. {
  862. this->FTPProxyType = 2;
  863. }
  864. else if ( type == "SOCKS5" )
  865. {
  866. this->FTPProxyType = 3;
  867. }
  868. }
  869. }
  870. if ( this->HTTPProxy.size() > 0 )
  871. {
  872. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use HTTP Proxy: "
  873. << this->HTTPProxy << std::endl);
  874. }
  875. if ( this->FTPProxy.size() > 0 )
  876. {
  877. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use FTP Proxy: "
  878. << this->FTPProxy << std::endl);
  879. }
  880. cmGeneratedFileStream ofs;
  881. this->StartLogFile("Submit", ofs);
  882. cmCTest::SetOfStrings files;
  883. std::string prefix = this->GetSubmitResultsPrefix();
  884. if (!this->Files.empty())
  885. {
  886. // Submit the explicitly selected files:
  887. //
  888. cmCTest::SetOfStrings::const_iterator it;
  889. for (it = this->Files.begin(); it != this->Files.end(); ++it)
  890. {
  891. files.insert(*it);
  892. }
  893. }
  894. // Add to the list of files to submit from any selected, existing parts:
  895. //
  896. // TODO:
  897. // Check if test is enabled
  898. this->CTest->AddIfExists(cmCTest::PartUpdate, "Update.xml");
  899. this->CTest->AddIfExists(cmCTest::PartConfigure, "Configure.xml");
  900. this->CTest->AddIfExists(cmCTest::PartBuild, "Build.xml");
  901. this->CTest->AddIfExists(cmCTest::PartTest, "Test.xml");
  902. if(this->CTest->AddIfExists(cmCTest::PartCoverage, "Coverage.xml"))
  903. {
  904. cmCTest::VectorOfStrings gfiles;
  905. std::string gpath
  906. = buildDirectory + "/Testing/" + this->CTest->GetCurrentTag();
  907. std::string::size_type glen = gpath.size() + 1;
  908. gpath = gpath + "/CoverageLog*";
  909. cmCTestLog(this->CTest, DEBUG, "Globbing for: " << gpath.c_str()
  910. << std::endl);
  911. if ( cmSystemTools::SimpleGlob(gpath, gfiles, 1) )
  912. {
  913. size_t cc;
  914. for ( cc = 0; cc < gfiles.size(); cc ++ )
  915. {
  916. gfiles[cc] = gfiles[cc].substr(glen);
  917. cmCTestLog(this->CTest, DEBUG, "Glob file: " << gfiles[cc].c_str()
  918. << std::endl);
  919. this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfiles[cc].c_str());
  920. }
  921. }
  922. else
  923. {
  924. cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl);
  925. }
  926. }
  927. this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml");
  928. this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml");
  929. this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml");
  930. // Query parts for files to submit.
  931. for(cmCTest::Part p = cmCTest::PartStart;
  932. p != cmCTest::PartCount; p = cmCTest::Part(p+1))
  933. {
  934. // Skip parts we are not submitting.
  935. if(!this->SubmitPart[p])
  936. {
  937. continue;
  938. }
  939. // Submit files from this part.
  940. std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
  941. for(std::vector<std::string>::const_iterator pi = pfiles.begin();
  942. pi != pfiles.end(); ++pi)
  943. {
  944. files.insert(*pi);
  945. }
  946. }
  947. if ( ofs )
  948. {
  949. ofs << "Upload files:" << std::endl;
  950. int cnt = 0;
  951. cmCTest::SetOfStrings::iterator it;
  952. for ( it = files.begin(); it != files.end(); ++ it )
  953. {
  954. ofs << cnt << "\t" << it->c_str() << std::endl;
  955. cnt ++;
  956. }
  957. }
  958. cmCTestLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
  959. << this->CTest->GetCTestConfiguration("DropMethod") << ")"
  960. << std::endl);
  961. const char* specificTrack = this->CTest->GetSpecificTrack();
  962. if ( specificTrack )
  963. {
  964. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Send to track: "
  965. << specificTrack << std::endl);
  966. }
  967. this->SetLogFile(&ofs);
  968. cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
  969. if ( dropMethod == "" || dropMethod == "ftp" )
  970. {
  971. ofs << "Using drop method: FTP" << std::endl;
  972. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using FTP submit method"
  973. << std::endl
  974. << " Drop site: ftp://");
  975. std::string url = "ftp://";
  976. url += cmCTest::MakeURLSafe(
  977. this->CTest->GetCTestConfiguration("DropSiteUser")) + ":" +
  978. cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration(
  979. "DropSitePassword")) + "@" +
  980. this->CTest->GetCTestConfiguration("DropSite") +
  981. cmCTest::MakeURLSafe(
  982. this->CTest->GetCTestConfiguration("DropLocation"));
  983. if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
  984. {
  985. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  986. this->CTest->GetCTestConfiguration(
  987. "DropSiteUser").c_str());
  988. if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
  989. {
  990. cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
  991. }
  992. cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
  993. }
  994. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  995. this->CTest->GetCTestConfiguration("DropSite")
  996. << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
  997. if ( !this->SubmitUsingFTP(buildDirectory + "/Testing/"
  998. + this->CTest->GetCurrentTag(),
  999. files, prefix, url) )
  1000. {
  1001. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1002. " Problems when submitting via FTP"
  1003. << std::endl);
  1004. ofs << " Problems when submitting via FTP" << std::endl;
  1005. return -1;
  1006. }
  1007. if(!this->CDash)
  1008. {
  1009. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
  1010. << std::endl
  1011. << " Trigger site: "
  1012. << this->CTest->GetCTestConfiguration("TriggerSite")
  1013. << std::endl);
  1014. if ( !this->
  1015. TriggerUsingHTTP(files, prefix,
  1016. this->CTest->GetCTestConfiguration("TriggerSite")))
  1017. {
  1018. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1019. " Problems when triggering via HTTP" << std::endl);
  1020. ofs << " Problems when triggering via HTTP" << std::endl;
  1021. return -1;
  1022. }
  1023. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  1024. << std::endl);
  1025. ofs << " Submission successful" << std::endl;
  1026. return 0;
  1027. }
  1028. }
  1029. else if ( dropMethod == "http" || dropMethod == "https" )
  1030. {
  1031. std::string url = dropMethod;
  1032. url += "://";
  1033. ofs << "Using drop method: " << dropMethod << std::endl;
  1034. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP submit method"
  1035. << std::endl
  1036. << " Drop site:" << url);
  1037. if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
  1038. {
  1039. url += this->CTest->GetCTestConfiguration("DropSiteUser");
  1040. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  1041. this->CTest->GetCTestConfiguration("DropSiteUser").c_str());
  1042. if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
  1043. {
  1044. url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
  1045. cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
  1046. }
  1047. url += "@";
  1048. cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
  1049. }
  1050. url += this->CTest->GetCTestConfiguration("DropSite") +
  1051. this->CTest->GetCTestConfiguration("DropLocation");
  1052. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  1053. this->CTest->GetCTestConfiguration("DropSite")
  1054. << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
  1055. if ( !this->SubmitUsingHTTP(buildDirectory + "/Testing/" +
  1056. this->CTest->GetCurrentTag(), files, prefix, url) )
  1057. {
  1058. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1059. " Problems when submitting via HTTP" << std::endl);
  1060. ofs << " Problems when submitting via HTTP" << std::endl;
  1061. return -1;
  1062. }
  1063. if(!this->CDash)
  1064. {
  1065. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
  1066. << std::endl
  1067. << " Trigger site: "
  1068. << this->CTest->GetCTestConfiguration("TriggerSite")
  1069. << std::endl);
  1070. if ( !this->
  1071. TriggerUsingHTTP(files, prefix,
  1072. this->CTest->GetCTestConfiguration("TriggerSite")))
  1073. {
  1074. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1075. " Problems when triggering via HTTP" << std::endl);
  1076. ofs << " Problems when triggering via HTTP" << std::endl;
  1077. return -1;
  1078. }
  1079. }
  1080. if(this->HasErrors)
  1081. {
  1082. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during "
  1083. "submission." << std::endl);
  1084. ofs << " Errors occurred during submission. " << std::endl;
  1085. }
  1086. else
  1087. {
  1088. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful" <<
  1089. (this->HasWarnings ? ", with warnings." : "") << std::endl);
  1090. ofs << " Submission successful" <<
  1091. (this->HasWarnings ? ", with warnings." : "") << std::endl;
  1092. }
  1093. return 0;
  1094. }
  1095. else if ( dropMethod == "xmlrpc" )
  1096. {
  1097. #if defined(CTEST_USE_XMLRPC)
  1098. ofs << "Using drop method: XML-RPC" << std::endl;
  1099. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using XML-RPC submit method"
  1100. << std::endl);
  1101. std::string url = this->CTest->GetCTestConfiguration("DropSite");
  1102. prefix = this->CTest->GetCTestConfiguration("DropLocation");
  1103. if ( !this->SubmitUsingXMLRPC(buildDirectory + "/Testing/" +
  1104. this->CTest->GetCurrentTag(), files, prefix, url) )
  1105. {
  1106. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1107. " Problems when submitting via XML-RPC" << std::endl);
  1108. ofs << " Problems when submitting via XML-RPC" << std::endl;
  1109. return -1;
  1110. }
  1111. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  1112. << std::endl);
  1113. ofs << " Submission successful" << std::endl;
  1114. return 0;
  1115. #else
  1116. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1117. " Submission method \"xmlrpc\" not compiled into CTest!"
  1118. << std::endl);
  1119. return -1;
  1120. #endif
  1121. }
  1122. else if ( dropMethod == "scp" )
  1123. {
  1124. std::string url;
  1125. std::string oldWorkingDirectory;
  1126. if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
  1127. {
  1128. url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@";
  1129. }
  1130. url += this->CTest->GetCTestConfiguration("DropSite") + ":" +
  1131. this->CTest->GetCTestConfiguration("DropLocation");
  1132. // change to the build directory so that we can uses a relative path
  1133. // on windows since scp dosn't support "c:" a drive in the path
  1134. oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
  1135. cmSystemTools::ChangeDirectory(buildDirectory.c_str());
  1136. if ( !this->SubmitUsingSCP(
  1137. this->CTest->GetCTestConfiguration("ScpCommand"),
  1138. "Testing/"+this->CTest->GetCurrentTag(), files, prefix, url) )
  1139. {
  1140. cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
  1141. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1142. " Problems when submitting via SCP"
  1143. << std::endl);
  1144. ofs << " Problems when submitting via SCP" << std::endl;
  1145. return -1;
  1146. }
  1147. cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
  1148. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  1149. << std::endl);
  1150. ofs << " Submission successful" << std::endl;
  1151. return 0;
  1152. }
  1153. else if ( dropMethod == "cp" )
  1154. {
  1155. std::string location
  1156. = this->CTest->GetCTestConfiguration("DropLocation");
  1157. // change to the build directory so that we can uses a relative path
  1158. // on windows since scp dosn't support "c:" a drive in the path
  1159. std::string
  1160. oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
  1161. cmSystemTools::ChangeDirectory(buildDirectory.c_str());
  1162. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Change directory: "
  1163. << buildDirectory.c_str() << std::endl);
  1164. if ( !this->SubmitUsingCP(
  1165. "Testing/"+this->CTest->GetCurrentTag(),
  1166. files,
  1167. prefix,
  1168. location) )
  1169. {
  1170. cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
  1171. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1172. " Problems when submitting via CP"
  1173. << std::endl);
  1174. ofs << " Problems when submitting via cp" << std::endl;
  1175. return -1;
  1176. }
  1177. cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
  1178. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  1179. << std::endl);
  1180. ofs << " Submission successful" << std::endl;
  1181. return 0;
  1182. }
  1183. cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \""
  1184. << dropMethod << "\"" << std::endl);
  1185. return -1;
  1186. }
  1187. //----------------------------------------------------------------------------
  1188. std::string cmCTestSubmitHandler::GetSubmitResultsPrefix()
  1189. {
  1190. std::string name = this->CTest->GetCTestConfiguration("Site") +
  1191. "___" + this->CTest->GetCTestConfiguration("BuildName") +
  1192. "___" + this->CTest->GetCurrentTag() + "-" +
  1193. this->CTest->GetTestModelString() + "___XML___";
  1194. return name;
  1195. }
  1196. //----------------------------------------------------------------------------
  1197. void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)
  1198. {
  1199. // Check whether each part is selected.
  1200. for(cmCTest::Part p = cmCTest::PartStart;
  1201. p != cmCTest::PartCount; p = cmCTest::Part(p+1))
  1202. {
  1203. this->SubmitPart[p] =
  1204. (std::set<cmCTest::Part>::const_iterator(parts.find(p)) != parts.end());
  1205. }
  1206. }
  1207. //----------------------------------------------------------------------------
  1208. void cmCTestSubmitHandler::SelectFiles(cmCTest::SetOfStrings const& files)
  1209. {
  1210. cmCTest::SetOfStrings::const_iterator it;
  1211. for (it = files.begin(); it != files.end(); ++it)
  1212. {
  1213. this->Files.insert(*it);
  1214. }
  1215. }