ws_fsBinding.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "ws_fsService.hpp"
  14. #include "ws_fsBinding.hpp"
  15. #include "TpWrapper.hpp"
  16. #include "environment.hpp"
  17. #include "jwrapper.hpp"
  18. #include "dfuwu.hpp"
  19. #include "dadfs.hpp"
  20. #include "exception_util.hpp"
  21. #define FILE_SPRAY_URL "FileSprayAccess"
  22. #define FILE_DESPRAY_URL "FileDesprayAccess"
  23. int CFileSpraySoapBindingEx::onGetInstantQuery(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method)
  24. {
  25. bool permission = true;
  26. bool bDownloadFile = false;
  27. bool bProcess;
  28. StringBuffer sourceLogicalFile;
  29. StringBuffer methodbuf;
  30. StringBuffer submethod;
  31. StringBuffer xsltFileName(getCFD());
  32. xsltFileName.append("smc_xslt/");
  33. if (stricmp(method, "SprayFixedInput")==0)
  34. {
  35. if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Write, false))
  36. permission = false;
  37. bProcess = true;
  38. xsltFileName.append("fs_sprayForm.xslt");
  39. methodbuf.append("SprayFixed");
  40. }
  41. else if(stricmp(method, "SprayVariableInput")==0)
  42. {
  43. if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Write, false))
  44. permission = false;
  45. bProcess = true;
  46. xsltFileName.append("fs_sprayForm.xslt");
  47. methodbuf.append("SprayVariable");
  48. request->getParameter("submethod", submethod);
  49. }
  50. else if (stricmp(method, "DesprayInput")==0)
  51. {
  52. if (!context.validateFeatureAccess(FILE_DESPRAY_URL, SecAccess_Write, false))
  53. permission = false;
  54. request->getParameter("sourceLogicalName", sourceLogicalFile);
  55. xsltFileName.append("fs_desprayCopyForm.xslt");
  56. methodbuf.append("Despray");
  57. bProcess = true;
  58. }
  59. else if (stricmp(method, "CopyInput") == 0)
  60. {
  61. if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Write, false))
  62. permission = false;
  63. request->getParameter("sourceLogicalName", sourceLogicalFile);
  64. xsltFileName.append("fs_desprayCopyForm.xslt");
  65. methodbuf.append("Copy");
  66. bProcess = true;
  67. }
  68. else if (stricmp(method, "RenameInput") == 0)
  69. {
  70. if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Write, false))
  71. permission = false;
  72. request->getParameter("sourceLogicalName", sourceLogicalFile);
  73. xsltFileName.append("fs_renameForm.xslt");
  74. methodbuf.append("Rename");
  75. bProcess = true;
  76. }
  77. else if (stricmp(method, "DownloadFile") == 0)
  78. {
  79. if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Full, false))
  80. permission = false;
  81. downloadFile(context, request, response);
  82. bDownloadFile = true;
  83. bProcess = true;
  84. }
  85. else
  86. bProcess = false;
  87. if (bProcess)
  88. {
  89. if (bDownloadFile)
  90. return 0;
  91. StringBuffer xml;
  92. Owned<IProperties> params(createProperties());
  93. if (!permission)
  94. {
  95. params->setProp("@method", methodbuf.str());
  96. xml.append("<Environment><ErrorMessage>Permission denied.</ErrorMessage></Environment>");
  97. }
  98. else
  99. {
  100. if(submethod.length() > 0)
  101. params->setProp("@submethod", submethod.str());
  102. params->setProp("@method", methodbuf.str());
  103. if (*sourceLogicalFile.str())
  104. {
  105. params->setProp("@sourceLogicalName", sourceLogicalFile.str());
  106. Owned<IUserDescriptor> userdesc;
  107. StringBuffer username;
  108. context.getUserID(username);
  109. if(username.length() > 0)
  110. {
  111. const char* passwd = context.queryPassword();
  112. userdesc.setown(createUserDescriptor());
  113. userdesc->set(username.str(), passwd);
  114. try
  115. {
  116. if (stricmp(method, "CopyInput") == 0)
  117. {
  118. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(sourceLogicalFile.str(), userdesc.get());
  119. if(!df)
  120. {
  121. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Could not find file %s.",sourceLogicalFile.str());
  122. }
  123. const char *kind = df->queryAttributes().queryProp("@kind");
  124. if (kind && strcmp(kind,"key")==0)
  125. {
  126. params->setProp("@compressflag", 0);
  127. }
  128. else if(df->isCompressed())
  129. {
  130. params->setProp("@compressflag", 2);
  131. }
  132. else
  133. {
  134. params->setProp("@compressflag", 1);
  135. }
  136. }
  137. }
  138. catch (IException *E)
  139. {
  140. Owned<IXslProcessor> xslp = getXslProcessor();
  141. if (!xslp)
  142. throw E;
  143. Owned<IMultiException> me = MakeMultiException();
  144. me->append(*E);
  145. response->handleExceptions(xslp, me, "FileSpray", method, StringBuffer(getCFD()).append("./smc_xslt/exceptions.xslt").str());
  146. return 0;
  147. }
  148. }
  149. }
  150. else
  151. {
  152. params->setProp("@compressflag", 1);
  153. }
  154. StringBuffer wuid;
  155. request->getParameter("wuid", wuid);
  156. Owned<IPropertyTree> pTree = createPTreeForXslt(method, wuid.str());
  157. toXML(pTree, xml, false);
  158. }
  159. IProperties* requestparams = request->queryParameters();
  160. if(requestparams && requestparams->hasProp("rawxml_"))
  161. {
  162. response->setContent(xml.str());
  163. response->setContentType(HTTP_TYPE_APPLICATION_XML);
  164. }
  165. else{
  166. StringBuffer htmlbuf;
  167. xsltTransform(xml.str(), xsltFileName.str(), params, htmlbuf);
  168. response->setContent(htmlbuf.str());
  169. response->setContentType(HTTP_TYPE_TEXT_HTML_UTF8);
  170. }
  171. response->send();
  172. return 0;
  173. }
  174. else
  175. return CFileSpraySoapBinding::onGetInstantQuery(context, request, response, service, method);
  176. }
  177. IPropertyTree* CFileSpraySoapBindingEx::createPTreeForXslt(const char* method, const char* dfuwuid)
  178. {
  179. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  180. Owned<IConstEnvironment> m_constEnv = factory->openEnvironment();
  181. Owned<IPropertyTree> pEnvRoot = &m_constEnv->getPTree();
  182. IPropertyTree* pEnvSoftware = pEnvRoot->queryPropTree("Software");
  183. Owned<IPropertyTree> pRoot = createPTreeFromXMLString("<Environment/>");
  184. IPropertyTree* pSoftware = pRoot->addPropTree("Software", createPTree("Software"));
  185. if (pEnvSoftware)
  186. {
  187. StringBuffer dfuwuidSourcePartIP, wuxml;
  188. if(dfuwuid && *dfuwuid)
  189. {
  190. Owned<IDFUWorkUnitFactory> dfuwu_factory = getDFUWorkUnitFactory();
  191. Owned<IConstDFUWorkUnit> dfuwu = dfuwu_factory->openWorkUnit(dfuwuid, false);
  192. if(dfuwu)
  193. {
  194. dfuwu->toXML(wuxml);
  195. Owned<IPropertyTree> wu = createPTreeFromXMLString(wuxml.str());
  196. if (wu)
  197. {
  198. const char* ip = wu->queryProp("Source/Part/@node");
  199. if (ip && *ip)
  200. dfuwuidSourcePartIP.append(ip);
  201. }
  202. }
  203. }
  204. Owned<IPropertyTreeIterator> it = pEnvSoftware->getElements("DropZone");
  205. ForEach(*it)
  206. {
  207. if (!it->query().getPropBool("@ECLWatchVisible", true))
  208. continue;
  209. IPropertyTree* pDropZone = pSoftware->addPropTree("DropZone", &it->get());
  210. //get IP Address of the computer associated with this drop zone
  211. const char* pszComputer = it->query().queryProp("@computer");
  212. if (!strcmp(pszComputer, "."))
  213. pszComputer = "localhost";
  214. StringBuffer xpath;
  215. xpath.appendf("Hardware/Computer[@name='%s']/@netAddress", pszComputer);
  216. StringBuffer sNetAddr;
  217. const char* pszNetAddr = pEnvRoot->queryProp(xpath.str());
  218. if (strcmp(pszNetAddr, "."))
  219. {
  220. sNetAddr.append(pszNetAddr);
  221. }
  222. else
  223. {
  224. StringBuffer ipStr;
  225. IpAddress ipaddr = queryHostIP();
  226. ipaddr.getIpText(ipStr);
  227. if (ipStr.length() > 0)
  228. {
  229. #ifdef MACHINE_IP
  230. sNetAddr.append(MACHINE_IP);
  231. #else
  232. sNetAddr.append(ipStr.str());
  233. #endif
  234. }
  235. }
  236. pDropZone->addProp("@netAddress", sNetAddr.str());
  237. if ((dfuwuidSourcePartIP.length() > 0) && (sNetAddr.length() > 0))
  238. {
  239. IpAddress ip1(dfuwuidSourcePartIP.str()), ip2(sNetAddr.str());
  240. if (ip1.ipequals(ip2))
  241. pDropZone->addProp("@sourceNode", "1");
  242. }
  243. Owned<IConstMachineInfo> machine;
  244. if (strcmp(pszNetAddr, "."))
  245. machine.setown(m_constEnv->getMachineByAddress(sNetAddr.str()));
  246. else
  247. {
  248. machine.setown(m_constEnv->getMachineByAddress(pszNetAddr));
  249. if (!machine)
  250. machine.setown(m_constEnv->getMachineByAddress(sNetAddr.str()));
  251. }
  252. if (machine)
  253. {
  254. //int os = machine->getOS();
  255. StringBuffer dir;
  256. pDropZone->getProp("@directory", dir);
  257. if (machine->getOS() == MachineOsLinux || machine->getOS() == MachineOsSolaris)
  258. {
  259. dir.replace('\\', '/');//replace all '\\' by '/'
  260. pDropZone->setProp("@linux", "true");
  261. }
  262. else
  263. {
  264. dir.replace('/', '\\');
  265. dir.replace('$', ':');
  266. }
  267. pDropZone->setProp("@directory", dir);
  268. }
  269. }
  270. //For Spray files on Thor Cluster, fetch all the group names for all the thor instances (and dedup them)
  271. BoolHash uniqueThorClusterGroupNames;
  272. it.setown(pEnvSoftware->getElements("ThorCluster"));
  273. ForEach(*it)
  274. {
  275. StringBuffer thorClusterGroupName;
  276. IPropertyTree& cluster = it->query();
  277. getClusterGroupName(cluster, thorClusterGroupName);
  278. if (!thorClusterGroupName.length())
  279. continue;
  280. bool* found = uniqueThorClusterGroupNames.getValue(thorClusterGroupName.str());
  281. if (found && *found)
  282. continue;
  283. uniqueThorClusterGroupNames.setValue(thorClusterGroupName.str(), true);
  284. IPropertyTree* newClusterTree = pSoftware->addPropTree("ThorCluster", &it->get());
  285. newClusterTree->setProp("@name", thorClusterGroupName.str()); //set group name into @name for spray target
  286. }
  287. it.setown(pEnvSoftware->getElements("EclAgentProcess"));
  288. ForEach(*it)
  289. {
  290. IPropertyTree &cluster = it->query();
  291. const char* name = cluster.queryProp("@name");
  292. if (!name||!*name)
  293. continue;
  294. unsigned ins = 0;
  295. Owned<IPropertyTreeIterator> insts = cluster.getElements("Instance");
  296. ForEach(*insts)
  297. {
  298. const char *na = insts->query().queryProp("@netAddress");
  299. if (!na || !*na)
  300. {
  301. insts->query().setProp("@gname", name);
  302. continue;
  303. }
  304. SocketEndpoint ep(na);
  305. if (ep.isNull())
  306. continue;
  307. ins++;
  308. StringBuffer gname("hthor__");
  309. //StringBuffer gname;
  310. gname.append(name);
  311. if (ins>1)
  312. gname.append('_').append(ins);
  313. insts->query().setProp("@gname", gname.str());
  314. }
  315. pSoftware->addPropTree("EclAgentProcess", &it->get());
  316. }
  317. if (stricmp(method, "CopyInput") == 0) //Limit for this method only
  318. {
  319. it.setown(pEnvSoftware->getElements("RoxieCluster"));
  320. ForEach(*it)
  321. pSoftware->addPropTree("RoxieCluster", &it->get());
  322. }
  323. if (wuxml.length() > 0)
  324. pSoftware->addPropTree("DfuWorkunit", createPTreeFromXMLString(wuxml.str()));
  325. }
  326. return pRoot.getClear();
  327. }
  328. void CFileSpraySoapBindingEx::xsltTransform(const char* xml, const char* sheet, IProperties *params, StringBuffer& ret)
  329. {
  330. StringBuffer xsl;
  331. if (!checkFileExists(sheet))
  332. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST, "Cannot open stylesheet %s",sheet);
  333. Owned<IXslProcessor> proc = getXslProcessor();
  334. Owned<IXslTransform> trans = proc->createXslTransform();
  335. trans->setXmlSource(xml, strlen(xml));
  336. trans->loadXslFromFile(sheet);
  337. if (params)
  338. {
  339. Owned<IPropertyIterator> it = params->getIterator();
  340. for (it->first(); it->isValid(); it->next())
  341. {
  342. const char *key = it->getPropKey();
  343. //set parameter in the XSL transform skipping over the @ prefix, if any
  344. const char* paramName = *key == '@' ? key+1 : key;
  345. trans->setParameter(paramName, StringBuffer().append('\'').append(params->queryProp(key)).append('\'').str());
  346. }
  347. }
  348. trans->transform(ret);
  349. }
  350. void CFileSpraySoapBindingEx::downloadFile(IEspContext &context, CHttpRequest* request, CHttpResponse* response)
  351. {
  352. try
  353. {
  354. StringBuffer netAddressStr, osStr, pathStr, nameStr;
  355. request->getParameter("NetAddress", netAddressStr);
  356. request->getParameter("OS", osStr);
  357. request->getParameter("Path", pathStr);
  358. request->getParameter("Name", nameStr);
  359. #if 0
  360. StringArray files;
  361. IProperties* params = request->queryParameters();
  362. Owned<IPropertyIterator> iter = params->getIterator();
  363. if (iter && iter->first())
  364. {
  365. while (iter->isValid())
  366. {
  367. const char *keyname=iter->getPropKey();
  368. if (!keyname || strncmp(keyname, "Names", 5))
  369. continue;
  370. files.append(params->queryProp(iter->getPropKey()));
  371. iter->next();
  372. }
  373. }
  374. #endif
  375. if (netAddressStr.length() < 1)
  376. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Network address not specified.");
  377. if (pathStr.length() < 1)
  378. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Path not specified.");
  379. if (nameStr.length() < 1)
  380. throw MakeStringException(ECLWATCH_INVALID_INPUT,"File name not specified.");
  381. char pathSep = '/';
  382. if ((osStr.length() > 1) && (atoi(osStr.str())== OS_WINDOWS))
  383. {
  384. pathSep = '\\';
  385. }
  386. pathStr.replace(pathSep=='\\'?'/':'\\', pathSep);
  387. if (*(pathStr.str() + pathStr.length() -1) != pathSep)
  388. pathStr.append( pathSep );
  389. StringBuffer fullName;
  390. fullName.appendf("%s%s", pathStr.str(), nameStr.str());
  391. StringBuffer headerStr("attachment;");
  392. headerStr.appendf("filename=%s", nameStr.str());
  393. RemoteFilename rfn;
  394. rfn.setRemotePath(fullName.str());
  395. SocketEndpoint ep(netAddressStr.str());
  396. rfn.setIp(ep);
  397. Owned<IFile> rFile = createIFile(rfn);
  398. if (!rFile)
  399. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot open file %s.",fullName.str());
  400. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  401. if (!rIO)
  402. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read file %s.",fullName.str());
  403. IFileIOStream* ioS = createIOStream(rIO);
  404. context.addCustomerHeader("Content-disposition", headerStr.str());
  405. response->setContent(ioS);
  406. response->setContentType(HTTP_TYPE_OCTET_STREAM);
  407. response->send();
  408. }
  409. catch(IException* e)
  410. {
  411. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  412. }
  413. return;
  414. }
  415. int CFileSpraySoapBindingEx::onFinishUpload(IEspContext &ctx, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method, StringArray& fileNames, StringArray& files, IMultiException *me)
  416. {
  417. if (!me || (me->ordinality()==0))
  418. {
  419. if (ctx.getResponseFormat()==ESPSerializationANY)
  420. {
  421. StringBuffer newUrl, netAddress, path;
  422. request->getParameter("NetAddress", netAddress);
  423. request->getParameter("Path", path);
  424. newUrl.appendf("/FileSpray/DropZoneFiles?NetAddress=%s&Path=%s", netAddress.str(), path.str());
  425. response->redirect(*request, newUrl.str());
  426. }
  427. else
  428. {
  429. IArrayOf<IEspDFUActionResult> results;
  430. Owned<CUploadFilesResponse> esp_response = new CUploadFilesResponse("FileSpray");
  431. ForEachItemIn(i, fileNames)
  432. {
  433. const char* fileName = fileNames.item(i);
  434. Owned<IEspDFUActionResult> res = createDFUActionResult("", "");
  435. res->setID(fileName);
  436. res->setAction("Upload File");
  437. res->setResult("Success");
  438. results.append(*res.getLink());
  439. }
  440. if (!results.length())
  441. {
  442. Owned<IEspDFUActionResult> res = createDFUActionResult("", "");
  443. res->setID("<N/A>");
  444. res->setAction("Upload File");
  445. res->setResult("No file uploaded");
  446. results.append(*res.getLink());
  447. }
  448. esp_response->setUploadFileResults(results);
  449. MemoryBuffer content;
  450. StringBuffer mimetype;
  451. esp_response->appendContent(&ctx,content, mimetype);
  452. response->setContent(content.length(), content.toByteArray());
  453. response->setContentType(mimetype.str());
  454. response->send();
  455. }
  456. }
  457. else
  458. {
  459. StringBuffer msg;
  460. WARNLOG("Exception(s) in EspHttpBinding::onStartUpload - %s", me->errorMessage(msg).append('\n').str());
  461. if ((ctx.getResponseFormat() == ESPSerializationXML) || (ctx.getResponseFormat() == ESPSerializationJSON))
  462. response->handleExceptions(NULL, me, "FileSpray", "UploadFile", NULL);
  463. else
  464. return EspHttpBinding::onFinishUpload(ctx, request, response, service, method, fileNames, files, me);
  465. }
  466. return 0;
  467. }