cmCTestSubmit.cxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmCTestSubmit.h"
  14. #include "cmSystemTools.h"
  15. #include <cmsys/Process.h>
  16. #include "CTest/Curl/curl/curl.h"
  17. #include <sys/stat.h>
  18. cmCTestSubmit::cmCTestSubmit() : m_HTTPProxy(), m_FTPProxy()
  19. {
  20. m_Verbose = false;
  21. m_HTTPProxy = "";
  22. m_HTTPProxyType = 0;
  23. m_HTTPProxyAuth = "";
  24. if ( getenv("HTTP_PROXY") )
  25. {
  26. m_HTTPProxyType = 1;
  27. m_HTTPProxy = getenv("HTTP_PROXY");
  28. if ( getenv("HTTP_PROXY_PORT") )
  29. {
  30. m_HTTPProxy += ":";
  31. m_HTTPProxy += getenv("HTTP_PROXY_PORT");
  32. }
  33. if ( getenv("HTTP_PROXY_TYPE") )
  34. {
  35. cmStdString type = getenv("HTTP_PROXY_TYPE");
  36. // HTTP/SOCKS4/SOCKS5
  37. if ( type == "HTTP" )
  38. {
  39. m_HTTPProxyType = 1;
  40. }
  41. else if ( type == "SOCKS4" )
  42. {
  43. m_HTTPProxyType = 2;
  44. }
  45. else if ( type == "SOCKS5" )
  46. {
  47. m_HTTPProxyType = 3;
  48. }
  49. }
  50. if ( getenv("HTTP_PROXY_USER") )
  51. {
  52. m_HTTPProxyAuth = getenv("HTTP_PROXY_USER");
  53. }
  54. if ( getenv("HTTP_PROXY_PASSWD") )
  55. {
  56. m_HTTPProxyAuth += ":";
  57. m_HTTPProxyAuth += getenv("HTTP_PROXY_PASSWD");
  58. }
  59. }
  60. m_FTPProxy = "";
  61. m_FTPProxyType = 0;
  62. if ( getenv("FTP_PROXY") )
  63. {
  64. m_FTPProxyType = 1;
  65. m_FTPProxy = getenv("FTP_PROXY");
  66. if ( getenv("FTP_PROXY_PORT") )
  67. {
  68. m_FTPProxy += ":";
  69. m_FTPProxy += getenv("FTP_PROXY_PORT");
  70. }
  71. if ( getenv("FTP_PROXY_TYPE") )
  72. {
  73. cmStdString type = getenv("FTP_PROXY_TYPE");
  74. // HTTP/SOCKS4/SOCKS5
  75. if ( type == "HTTP" )
  76. {
  77. m_FTPProxyType = 1;
  78. }
  79. else if ( type == "SOCKS4" )
  80. {
  81. m_FTPProxyType = 2;
  82. }
  83. else if ( type == "SOCKS5" )
  84. {
  85. m_FTPProxyType = 3;
  86. }
  87. }
  88. }
  89. if ( m_HTTPProxy.size() > 0 )
  90. {
  91. std::cout << " Use HTTP Proxy: " << m_HTTPProxy << std::endl;
  92. }
  93. if ( m_FTPProxy.size() > 0 )
  94. {
  95. std::cout << " Use FTP Proxy: " << m_FTPProxy << std::endl;
  96. }
  97. }
  98. bool cmCTestSubmit::SubmitUsingFTP(const cmStdString& localprefix,
  99. const std::vector<cmStdString>& files,
  100. const cmStdString& remoteprefix,
  101. const cmStdString& url)
  102. {
  103. CURL *curl;
  104. CURLcode res;
  105. FILE* ftpfile;
  106. char error_buffer[1024];
  107. /* In windows, this will init the winsock stuff */
  108. ::curl_global_init(CURL_GLOBAL_ALL);
  109. cmStdString::size_type cc;
  110. for ( cc = 0; cc < files.size(); cc ++ )
  111. {
  112. /* get a curl handle */
  113. curl = curl_easy_init();
  114. if(curl)
  115. {
  116. // Using proxy
  117. if ( m_FTPProxyType > 0 )
  118. {
  119. curl_easy_setopt(curl, CURLOPT_PROXY, m_FTPProxy.c_str());
  120. switch (m_FTPProxyType)
  121. {
  122. case 2:
  123. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  124. break;
  125. case 3:
  126. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  127. break;
  128. default:
  129. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  130. }
  131. }
  132. // enable uploading
  133. ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1) ;
  134. cmStdString local_file = localprefix + "/" + files[cc];
  135. cmStdString upload_as = url + "/" + remoteprefix + files[cc];
  136. struct stat st;
  137. if ( ::stat(local_file.c_str(), &st) )
  138. {
  139. return false;
  140. }
  141. ftpfile = ::fopen(local_file.c_str(), "rb");
  142. *m_LogFile << "\tUpload file: " << local_file.c_str() << " to "
  143. << upload_as.c_str() << std::endl;
  144. if ( m_Verbose )
  145. {
  146. std::cout << " Upload file: " << local_file.c_str() << " to "
  147. << upload_as.c_str() << std::endl;
  148. }
  149. if ( m_Verbose )
  150. {
  151. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  152. }
  153. // specify target
  154. ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
  155. // now specify which file to upload
  156. ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
  157. // and give the size of the upload (optional)
  158. ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, static_cast<long>(st.st_size));
  159. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  160. // Now run off and do what you've been told!
  161. res = ::curl_easy_perform(curl);
  162. fclose(ftpfile);
  163. if ( res )
  164. {
  165. std::cerr << " Error when uploading file: " << local_file.c_str() << std::endl;
  166. std::cerr << " Error message was: " << error_buffer << std::endl;
  167. *m_LogFile << " Error when uploading file: " << local_file.c_str() << std::endl
  168. << " Error message was: " << error_buffer << std::endl;
  169. ::curl_easy_cleanup(curl);
  170. ::curl_global_cleanup();
  171. return false;
  172. }
  173. // always cleanup
  174. ::curl_easy_cleanup(curl);
  175. std::cout << " Uploaded: " + local_file << std::endl;
  176. }
  177. }
  178. ::curl_global_cleanup();
  179. return true;
  180. }
  181. // Uploading files is simpler
  182. bool cmCTestSubmit::SubmitUsingHTTP(const cmStdString& localprefix,
  183. const std::vector<cmStdString>& files,
  184. const cmStdString& remoteprefix,
  185. const cmStdString& url)
  186. {
  187. CURL *curl;
  188. CURLcode res;
  189. FILE* ftpfile;
  190. char error_buffer[1024];
  191. /* In windows, this will init the winsock stuff */
  192. ::curl_global_init(CURL_GLOBAL_ALL);
  193. cmStdString::size_type cc, kk;
  194. for ( cc = 0; cc < files.size(); cc ++ )
  195. {
  196. /* get a curl handle */
  197. curl = curl_easy_init();
  198. if(curl)
  199. {
  200. // Using proxy
  201. if ( m_HTTPProxyType > 0 )
  202. {
  203. curl_easy_setopt(curl, CURLOPT_PROXY, m_HTTPProxy.c_str());
  204. switch (m_HTTPProxyType)
  205. {
  206. case 2:
  207. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  208. break;
  209. case 3:
  210. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  211. break;
  212. default:
  213. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  214. if (m_HTTPProxyAuth.size() > 0)
  215. {
  216. curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
  217. m_HTTPProxyAuth.c_str());
  218. }
  219. }
  220. }
  221. /* enable uploading */
  222. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1) ;
  223. /* HTTP PUT please */
  224. curl_easy_setopt(curl, CURLOPT_PUT, 1);
  225. if ( m_Verbose )
  226. {
  227. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  228. }
  229. cmStdString local_file = localprefix + "/" + files[cc];
  230. cmStdString remote_file = remoteprefix + files[cc];
  231. *m_LogFile << "\tUpload file: " << local_file.c_str() << " to "
  232. << remote_file.c_str() << std::endl;
  233. cmStdString ofile = "";
  234. for ( kk = 0; kk < remote_file.size(); kk ++ )
  235. {
  236. char c = remote_file[kk];
  237. char hex[4] = { 0, 0, 0, 0 };
  238. hex[0] = c;
  239. switch ( c )
  240. {
  241. case '+':
  242. case '?':
  243. case '/':
  244. case '\\':
  245. case '&':
  246. case ' ':
  247. case '=':
  248. case '%':
  249. sprintf(hex, "%%%02X", (int)c);
  250. ofile.append(hex);
  251. break;
  252. default:
  253. ofile.append(hex);
  254. }
  255. }
  256. cmStdString upload_as
  257. = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
  258. + "FileName=" + ofile;
  259. struct stat st;
  260. if ( ::stat(local_file.c_str(), &st) )
  261. {
  262. return false;
  263. }
  264. ftpfile = ::fopen(local_file.c_str(), "rb");
  265. if ( m_Verbose )
  266. {
  267. std::cout << " Upload file: " << local_file.c_str() << " to "
  268. << upload_as.c_str() << " Size: " << st.st_size << std::endl;
  269. }
  270. // specify target
  271. ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
  272. // now specify which file to upload
  273. ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
  274. // and give the size of the upload (optional)
  275. ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, static_cast<long>(st.st_size));
  276. // and give curl the buffer for errors
  277. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  278. // Now run off and do what you've been told!
  279. res = ::curl_easy_perform(curl);
  280. fclose(ftpfile);
  281. if ( res )
  282. {
  283. std::cerr << " Error when uploading file: " << local_file.c_str() << std::endl;
  284. *m_LogFile << " Error when uploading file: " << local_file.c_str() << std::endl
  285. << " Error message was: " << error_buffer << std::endl;
  286. ::curl_easy_cleanup(curl);
  287. ::curl_global_cleanup();
  288. return false;
  289. }
  290. // always cleanup
  291. ::curl_easy_cleanup(curl);
  292. std::cout << " Uploaded: " + local_file << std::endl;
  293. }
  294. }
  295. ::curl_global_cleanup();
  296. return true;
  297. }
  298. bool cmCTestSubmit::TriggerUsingHTTP(const std::vector<cmStdString>& files,
  299. const cmStdString& remoteprefix,
  300. const cmStdString& url)
  301. {
  302. CURL *curl;
  303. char error_buffer[1024];
  304. /* In windows, this will init the winsock stuff */
  305. ::curl_global_init(CURL_GLOBAL_ALL);
  306. cmStdString::size_type cc, kk;
  307. for ( cc = 0; cc < files.size(); cc ++ )
  308. {
  309. /* get a curl handle */
  310. curl = curl_easy_init();
  311. if(curl)
  312. {
  313. // Using proxy
  314. if ( m_HTTPProxyType > 0 )
  315. {
  316. curl_easy_setopt(curl, CURLOPT_PROXY, m_HTTPProxy.c_str());
  317. switch (m_HTTPProxyType)
  318. {
  319. case 2:
  320. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  321. break;
  322. case 3:
  323. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  324. break;
  325. default:
  326. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  327. if (m_HTTPProxyAuth.size() > 0)
  328. {
  329. curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
  330. m_HTTPProxyAuth.c_str());
  331. }
  332. }
  333. }
  334. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
  335. if ( m_Verbose )
  336. {
  337. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  338. }
  339. // and give curl the buffer for errors
  340. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  341. cmStdString file = remoteprefix + files[cc];
  342. cmStdString ofile = "";
  343. for ( kk = 0; kk < file.size(); kk ++ )
  344. {
  345. char c = file[kk];
  346. char hex[4] = { 0, 0, 0, 0 };
  347. hex[0] = c;
  348. switch ( c )
  349. {
  350. case '+':
  351. case '?':
  352. case '/':
  353. case '\\':
  354. case '&':
  355. case ' ':
  356. case '=':
  357. case '%':
  358. sprintf(hex, "%%%02X", (int)c);
  359. ofile.append(hex);
  360. break;
  361. default:
  362. ofile.append(hex);
  363. }
  364. }
  365. cmStdString turl
  366. = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
  367. + "xmlfile=" + ofile;
  368. *m_LogFile << "Trigger url: " << turl.c_str() << std::endl;
  369. if ( m_Verbose )
  370. {
  371. std::cout << " Trigger url: " << turl.c_str() << std::endl;
  372. }
  373. curl_easy_setopt(curl, CURLOPT_URL, turl.c_str());
  374. if ( curl_easy_perform(curl) )
  375. {
  376. std::cerr << " Error when triggering: " << turl.c_str() << std::endl;
  377. *m_LogFile << "\tTrigerring failed with error: " << error_buffer << std::endl;
  378. ::curl_easy_cleanup(curl);
  379. ::curl_global_cleanup();
  380. return false;
  381. }
  382. // always cleanup
  383. ::curl_easy_cleanup(curl);
  384. std::cout << std::endl;
  385. }
  386. }
  387. ::curl_global_cleanup();
  388. std::cout << " Dart server triggered..." << std::endl;
  389. return true;
  390. }
  391. bool cmCTestSubmit::SubmitUsingSCP(
  392. const cmStdString& scp_command,
  393. const cmStdString& localprefix,
  394. const std::vector<cmStdString>& files,
  395. const cmStdString& remoteprefix,
  396. const cmStdString& url)
  397. {
  398. if ( !scp_command.size() || !localprefix.size() ||
  399. !files.size() || !remoteprefix.size() || !url.size() )
  400. {
  401. return 0;
  402. }
  403. std::vector<const char*> argv;
  404. argv.push_back(scp_command.c_str()); // Scp command
  405. argv.push_back(scp_command.c_str()); // Dummy string for file
  406. argv.push_back(scp_command.c_str()); // Dummy string for remote url
  407. argv.push_back(0);
  408. cmsysProcess* cp = cmsysProcess_New();
  409. cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
  410. //cmsysProcess_SetTimeout(cp, timeout);
  411. int problems = 0;
  412. std::vector<cmStdString>::const_iterator it;
  413. for ( it = files.begin();
  414. it != files.end();
  415. it ++ )
  416. {
  417. int retVal;
  418. std::string lfname = localprefix;
  419. cmSystemTools::ConvertToUnixSlashes(lfname);
  420. lfname += "/" + *it;
  421. lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
  422. argv[1] = lfname.c_str();
  423. std::string rfname = url + "/" + remoteprefix + *it;
  424. argv[2] = rfname.c_str();
  425. if ( m_Verbose )
  426. {
  427. std::cout << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
  428. << argv[2] << "\"" << std::endl;
  429. }
  430. *m_LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
  431. << argv[2] << "\"" << std::endl;
  432. cmsysProcess_SetCommand(cp, &*argv.begin());
  433. cmsysProcess_Execute(cp);
  434. char* data;
  435. int length;
  436. while(cmsysProcess_WaitForData(cp, &data, &length, 0))
  437. {
  438. std::cout.write(data, length);
  439. }
  440. cmsysProcess_WaitForExit(cp, 0);
  441. int result = cmsysProcess_GetState(cp);
  442. if(result == cmsysProcess_State_Exited)
  443. {
  444. retVal = cmsysProcess_GetExitValue(cp);
  445. if ( retVal != 0 )
  446. {
  447. if ( m_Verbose )
  448. {
  449. std::cout << "\tSCP returned: " << retVal << std::endl;
  450. }
  451. *m_LogFile << "\tSCP returned: " << retVal << std::endl;
  452. problems ++;
  453. }
  454. }
  455. else if(result == cmsysProcess_State_Exception)
  456. {
  457. retVal = cmsysProcess_GetExitException(cp);
  458. if ( m_Verbose )
  459. {
  460. std::cerr << "\tThere was an exception: " << retVal << std::endl;
  461. }
  462. *m_LogFile << "\tThere was an exception: " << retVal << std::endl;
  463. problems ++;
  464. }
  465. else if(result == cmsysProcess_State_Expired)
  466. {
  467. if ( m_Verbose )
  468. {
  469. std::cerr << "\tThere was a timeout" << std::endl;
  470. }
  471. *m_LogFile << "\tThere was a timeout" << std::endl;
  472. problems ++;
  473. }
  474. else if(result == cmsysProcess_State_Error)
  475. {
  476. if ( m_Verbose )
  477. {
  478. std::cerr << "\tError executing SCP: "
  479. << cmsysProcess_GetErrorString(cp) << std::endl;
  480. }
  481. *m_LogFile << "\tError executing SCP: "
  482. << cmsysProcess_GetErrorString(cp) << std::endl;
  483. problems ++;
  484. }
  485. }
  486. cmsysProcess_Delete(cp);
  487. if ( problems )
  488. {
  489. return false;
  490. }
  491. return true;
  492. }