Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

updatablefile.cpp 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. *
  3. * Copyright (C) 1995-2011 Opera Software AS. All rights reserved.
  4. *
  5. * This file is part of the Opera web browser. It may not be distributed
  6. * under any circumstances.
  7. *
  8. * @author Marius Blomli, Michal Zajaczkowski
  9. */
  10. #include "core/pch.h"
  11. #ifdef AUTO_UPDATE_SUPPORT
  12. #include "adjunct/autoupdate/updatablefile.h"
  13. #include "adjunct/autoupdate/signed_file.h"
  14. #include "adjunct/autoupdate/autoupdate_key.h"
  15. #include "adjunct/desktop_util/version/operaversion.h"
  16. #ifdef AUTOUPDATE_PACKAGE_INSTALLATION
  17. # include "adjunct/autoupdate/updater/pi/aufileutils.h"
  18. # include "adjunct/autoupdate/pi/opautoupdatepi.h"
  19. # include "adjunct/autoupdate/updater/audatafile.h"
  20. #endif
  21. #include "adjunct/desktop_util/opfile/desktop_opfile.h"
  22. #include "adjunct/quick/dialogs/TrustedProtocolDialog.h" // Defines TrustedProtocolList
  23. #include "modules/url/url2.h"
  24. #include "modules/prefs/prefsmanager/collections/pc_ui.h"
  25. #include "modules/util/opfile/opfile.h"
  26. #include "modules/dom/domenvironment.h"
  27. #include "modules/prefs/prefsmanager/collections/pc_js.h"
  28. #include "modules/prefs/prefsmanager/prefsmanager.h"
  29. #include "modules/spellchecker/opspellcheckerapi.h"
  30. #include "platforms/vega_backends/vega_blocklist_file.h"
  31. #ifdef PLUGIN_AUTO_INSTALL
  32. #include "adjunct/quick/managers/PluginInstallManager.h"
  33. #include "adjunct/desktop_pi/launch_pi.h"
  34. #endif // PLUGIN_AUTO_INSTALL
  35. UpdatableFile::UpdatableFile()
  36. {
  37. }
  38. BOOL UpdatableFile::CheckResource()
  39. {
  40. OpString signature;
  41. OpString8 signature8;
  42. OpString target_filename;
  43. RETURN_VALUE_IF_ERROR(GetTargetFilename(target_filename), FALSE);
  44. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_CHECKSUM, signature), FALSE);
  45. RETURN_VALUE_IF_ERROR(signature8.Set(signature), FALSE);
  46. if(OpStatus::IsSuccess(CheckFileSignature(target_filename, signature8)))
  47. {
  48. return TRUE;
  49. }
  50. else
  51. {
  52. OpString message;
  53. message.AppendFormat(UNI_L("Signature verification failed for %s"), target_filename.CStr());
  54. Console::WriteError(message.CStr());
  55. return FALSE;
  56. }
  57. }
  58. OP_STATUS UpdatableFile::GetDownloadFullName(OpString& full_filename)
  59. {
  60. OpString file_name;
  61. RETURN_IF_ERROR(GetAttrValue(URA_NAME, file_name));
  62. RETURN_IF_ERROR(GetDownloadFolder(full_filename));
  63. RETURN_IF_ERROR(full_filename.Append(file_name));
  64. return OpStatus::OK;
  65. }
  66. OP_STATUS UpdatableFile::GetDownloadFolder(OpString& download_folder)
  67. {
  68. return g_folder_manager->GetFolderPath(OPFILE_TEMPDOWNLOAD_FOLDER, download_folder);
  69. }
  70. OP_STATUS UpdatableFile::StartDownloading(FileDownloadListener* listener)
  71. {
  72. OP_ASSERT(listener);
  73. if (!listener)
  74. return OpStatus::ERR;
  75. OpString url;
  76. OpString target_filename;
  77. // The empty HasContent() check below is enough
  78. RETURN_IF_ERROR(GetAttrValue(URA_URL, url));
  79. RETURN_IF_ERROR(GetDownloadFullName(target_filename));
  80. if (url.HasContent() && target_filename.HasContent())
  81. {
  82. SetFileDownloadListener(listener);
  83. return StartDownload(url, target_filename);
  84. }
  85. else
  86. return OpStatus::ERR;
  87. }
  88. OpFileLength UpdatableFile::GetOverridedFileLength()
  89. {
  90. int size = 0;
  91. if (OpStatus::IsError(GetAttrValue(URA_SIZE, size)))
  92. return 0;
  93. return size;
  94. }
  95. BOOL UpdatablePackage::VerifyAttributes()
  96. {
  97. URAttr mandatory[] =
  98. {
  99. URA_NAME,
  100. URA_VERSION,
  101. URA_BUILDNUM,
  102. URA_URL,
  103. URA_TYPE,
  104. URA_CHECKSUM
  105. };
  106. int count = ARRAY_SIZE(mandatory);
  107. for (int i=0; i<count; i++)
  108. if (!HasAttrWithContent(mandatory[i]))
  109. return FALSE;
  110. OpString version, buildnum;
  111. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_VERSION, version), FALSE);
  112. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_BUILDNUM, buildnum), FALSE);
  113. // Check that provided upgrade version is higher than current
  114. OperaVersion upgrade_version;
  115. OpString version_string;
  116. RETURN_VALUE_IF_ERROR(version_string.Set(version), FALSE);
  117. RETURN_VALUE_IF_ERROR(version_string.Append("."), FALSE);
  118. RETURN_VALUE_IF_ERROR(version_string.Append(buildnum), FALSE);
  119. RETURN_VALUE_IF_ERROR(upgrade_version.Set(version_string), FALSE);
  120. // Check that downloaded version is higher
  121. if(AutoUpdater::GetOperaVersion() >= upgrade_version)
  122. {
  123. Console::WriteError(UNI_L("Current version is higher than provided version."));
  124. return FALSE;
  125. }
  126. return TRUE;
  127. }
  128. BOOL UpdatablePackage::GetShowNotification()
  129. {
  130. OpString string;
  131. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_SHOWDIALOG, string), FALSE);
  132. return string.CompareI(UNI_L("true")) == 0;
  133. }
  134. OP_STATUS UpdatablePackage::UpdateResource()
  135. {
  136. #ifndef AUTOUPDATE_PACKAGE_INSTALLATION
  137. return OpStatus::ERR_NOT_SUPPORTED;
  138. #else
  139. uni_char* exe_path = NULL;
  140. AUFileUtils* file_utils = AUFileUtils::Create();
  141. if (!file_utils)
  142. return OpStatus::ERR_NO_MEMORY;
  143. if(file_utils->GetExePath(&exe_path) != AUFileUtils::OK)
  144. {
  145. OP_DELETE(file_utils);
  146. return OpStatus::ERR;
  147. }
  148. OpString exe_path_str;
  149. RETURN_IF_ERROR(exe_path_str.Set(exe_path));
  150. OP_DELETEA(exe_path);
  151. uni_char* upgrade_folder = NULL;
  152. if(file_utils->GetUpgradeFolder(&upgrade_folder) != AUFileUtils::OK)
  153. {
  154. OP_DELETE(file_utils);
  155. return OpStatus::ERR;
  156. }
  157. // Delete the upgrade folder
  158. OpFile upgrade_path;
  159. if(OpStatus::IsSuccess(upgrade_path.Construct(upgrade_folder, OPFILE_ABSOLUTE_FOLDER)))
  160. {
  161. OpStatus::Ignore(upgrade_path.Delete(TRUE));
  162. }
  163. // Copy downloaded package to upgrade folder
  164. OpFile source_package;
  165. RETURN_IF_ERROR(source_package.Construct(m_file_name, OPFILE_ABSOLUTE_FOLDER));
  166. OpString dest_name;
  167. RETURN_IF_ERROR(dest_name.Set(upgrade_folder));
  168. RETURN_IF_ERROR(dest_name.Append(source_package.GetName()));
  169. OpFile dest_package;
  170. RETURN_IF_ERROR(dest_package.Construct(dest_name, OPFILE_ABSOLUTE_FOLDER));
  171. RETURN_IF_ERROR(dest_package.CopyContents(&source_package, FALSE));
  172. AUDataFile au_datafile;
  173. OpString version, buildnum;
  174. RETURN_IF_ERROR(GetAttrValue(URA_VERSION, version));
  175. RETURN_IF_ERROR(GetAttrValue(URA_BUILDNUM, buildnum));
  176. if(OpStatus::IsError(au_datafile.Init()) ||
  177. OpStatus::IsError(au_datafile.SetInstallPath(exe_path_str.CStr())) ||
  178. OpStatus::IsError(au_datafile.SetUpdateFile(dest_package.GetFullPath(), AUDataFile::Full)) ||
  179. OpStatus::IsError(au_datafile.SetVersion(version)) ||
  180. OpStatus::IsError(au_datafile.SetBuildnum(buildnum)) ||
  181. OpStatus::IsError(au_datafile.Write()))
  182. {
  183. OP_DELETE(file_utils);
  184. return OpStatus::ERR;
  185. }
  186. // Copy the internal Update.exe to Update.exe is the special folder
  187. uni_char* update_source_path = NULL;
  188. OpString update_name_from;
  189. // Get the name of the update
  190. if(file_utils->GetUpgradeSourcePath(&update_source_path) != AUFileUtils::OK)
  191. {
  192. OP_DELETE(file_utils);
  193. OP_DELETEA(update_source_path);
  194. return OpStatus::ERR;
  195. }
  196. OP_STATUS rtn = update_name_from.Set(update_source_path);
  197. OP_DELETEA(update_source_path);
  198. RETURN_IF_ERROR(rtn);
  199. // Build the to name
  200. uni_char* update_path = NULL;
  201. OpString update_name_to;
  202. // Get the name of the update
  203. if(file_utils->GetUpdatePath(&update_path) != AUFileUtils::OK)
  204. {
  205. OP_DELETE(file_utils);
  206. OP_DELETEA(update_path);
  207. return OpStatus::ERR;
  208. }
  209. rtn = update_name_to.Set(update_path);
  210. OP_DELETEA(update_path);
  211. RETURN_IF_ERROR(rtn);
  212. // Copy the locations which could be a file or folder
  213. OpFile target, src;
  214. target.Construct(update_name_to.CStr());
  215. src.Construct(update_name_from.CStr());
  216. rtn = DesktopOpFileUtils::Copy(target, src, TRUE, FALSE);
  217. if(OpStatus::IsError(rtn))
  218. {
  219. au_datafile.Delete();
  220. return rtn;
  221. }
  222. OP_DELETE(file_utils);
  223. OpAutoUpdatePI* autoupdate_pi = OpAutoUpdatePI::Create();
  224. if(!autoupdate_pi)
  225. return OpStatus::ERR_NO_MEMORY;
  226. // Extract the files needed to launch the installation
  227. if (autoupdate_pi->ExtractInstallationFiles(dest_name.CStr()) != AUFileUtils::OK)
  228. {
  229. OP_DELETE(autoupdate_pi);
  230. return OpStatus::ERR;
  231. }
  232. OP_DELETE(autoupdate_pi);
  233. return OpStatus::OK;
  234. #endif
  235. }
  236. BOOL UpdatablePackage::UpdateRequiresUnpacking()
  237. {
  238. #ifdef AUTOUPDATE_PACKAGE_INSTALLATION
  239. OpAutoUpdatePI* autoupdate_pi = OpAutoUpdatePI::Create();
  240. if(!autoupdate_pi)
  241. return FALSE;
  242. BOOL ret = autoupdate_pi->ExtractionInBackground();
  243. OP_DELETE(autoupdate_pi);
  244. return ret;
  245. #else
  246. return FALSE;
  247. #endif
  248. }
  249. BOOL UpdatablePackage::CheckResource()
  250. {
  251. OpString version_attr, buildnum_attr;
  252. OperaVersion version;
  253. OpString version_string;
  254. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_VERSION, version_attr), FALSE);
  255. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_BUILDNUM, buildnum_attr), FALSE);
  256. RETURN_VALUE_IF_ERROR(version_string.Set(version_attr), FALSE);
  257. RETURN_VALUE_IF_ERROR(version_string.Append("."), FALSE);
  258. RETURN_VALUE_IF_ERROR(version_string.Append(buildnum_attr), FALSE);
  259. RETURN_VALUE_IF_ERROR(version.Set(version_string), FALSE);
  260. // Check that downloaded version is higher
  261. if(AutoUpdater::GetOperaVersion() >= version)
  262. {
  263. Console::WriteError(UNI_L("Current version is higher than downloaded version."));
  264. return FALSE;
  265. }
  266. return UpdatableFile::CheckResource();
  267. }
  268. OP_STATUS UpdatablePackage::GetPackageVersion(OperaVersion& version)
  269. {
  270. OpString version_attr, buildno_atrr;
  271. RETURN_IF_ERROR(GetAttrValue(URA_VERSION, version_attr));
  272. RETURN_IF_ERROR(GetAttrValue(URA_BUILDNUM, buildno_atrr));
  273. return version.Set(version_attr.CStr(), buildno_atrr.CStr());
  274. }
  275. OP_STATUS UpdatablePackage::Cleanup()
  276. {
  277. FileDownloader::CleanUp();
  278. return DeleteDownloadedFile();
  279. }
  280. OP_STATUS UpdatableSpoof::UpdateResource()
  281. {
  282. OpString url_string;
  283. OpString resolved;
  284. BOOL successful = FALSE;
  285. int timestamp = 0;
  286. RETURN_IF_ERROR(url_string.Set(UNI_L("file:")));
  287. RETURN_IF_ERROR(url_string.Append(m_file_name));
  288. RETURN_IF_LEAVE(successful = g_url_api->ResolveUrlNameL(url_string, resolved));
  289. if (!successful || resolved.Find("file://") != 0)
  290. return OpStatus::ERR;
  291. URL url = g_url_api->GetURL(resolved.CStr());
  292. RETURN_IF_ERROR(g_PrefsLoadManager->InitLoader(url, OP_NEW(EndChecker,)));
  293. RETURN_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp));
  294. TRAP_AND_RETURN(res, g_pcui->WriteIntegerL(PrefsCollectionUI::SpoofTime, timestamp));
  295. TRAP_AND_RETURN(res, g_prefsManager->CommitL());
  296. return OpStatus::OK;
  297. }
  298. BOOL UpdatableSpoof::CheckResource()
  299. {
  300. int timestamp;
  301. time_t current_timestamp = g_pcui->GetIntegerPref(PrefsCollectionUI::SpoofTime);
  302. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp), FALSE);
  303. if(current_timestamp >= timestamp)
  304. {
  305. Console::WriteError(UNI_L("Invalid timestamp for spoof file."));
  306. return FALSE;
  307. }
  308. // Disabled for now, spoof files are generated on the fly so no checksum yet.
  309. //return UpdatableFile::CheckResource();
  310. return TRUE;
  311. }
  312. OP_STATUS UpdatableSpoof::Cleanup()
  313. {
  314. // The loading of the spoof is done asynchrous so we cant delete it before its finished
  315. FileDownloader::CleanUp();
  316. return OpStatus::OK;
  317. }
  318. BOOL UpdatableSpoof::VerifyAttributes()
  319. {
  320. // Check if all the needed attributes were sent with the response XML for this file resource
  321. // We need the filename
  322. if (!HasAttrWithContent(URA_NAME))
  323. return FALSE;
  324. // Either the URL or the alternative URL needs to be present
  325. if (!HasAttrWithContent(URA_URL) && !HasAttrWithContent(URA_URLALT))
  326. return FALSE;
  327. // The timestamp has to be present
  328. if (!HasAttrWithContent(URA_TIMESTAMP))
  329. return FALSE;
  330. return TRUE;
  331. }
  332. OP_STATUS UpdatableBrowserJS::UpdateResource()
  333. {
  334. // Copy downloaded browser.js file to home folder.
  335. OpFile local_file;
  336. OpFile temp_browser_js_file;
  337. OpString local_file_name;
  338. int timestamp = 0;
  339. RETURN_IF_ERROR(g_folder_manager->GetFolderPath(OPFILE_HOME_FOLDER, local_file_name));
  340. if(local_file_name.Length() <= 0)
  341. return OpStatus::ERR;
  342. RETURN_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp));
  343. RETURN_IF_ERROR(local_file_name.Append("browser.js"));
  344. RETURN_IF_ERROR(local_file.Construct(local_file_name.CStr()));
  345. RETURN_IF_ERROR(temp_browser_js_file.Construct(m_file_name.CStr()));
  346. RETURN_IF_ERROR(local_file.CopyContents(&temp_browser_js_file, FALSE));
  347. // Write the setting
  348. TRAP_AND_RETURN(res, g_pcjs->WriteIntegerL(PrefsCollectionJS::BrowserJSSetting, 2));
  349. TRAP_AND_RETURN(res, g_pcui->WriteIntegerL(PrefsCollectionUI::BrowserJSTime, timestamp));
  350. TRAP_AND_RETURN(res, g_prefsManager->CommitL());
  351. return OpStatus::OK;
  352. }
  353. BOOL UpdatableBrowserJS::CheckResource()
  354. {
  355. int timestamp;
  356. time_t current_timestamp = g_pcui->GetIntegerPref(PrefsCollectionUI::BrowserJSTime);
  357. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp), FALSE);
  358. if(current_timestamp >= timestamp)
  359. {
  360. Console::WriteError(UNI_L("Invalid timestamp for browser js file."));
  361. return FALSE;
  362. }
  363. // Check if the intermediate file is ok
  364. OpFile temp_browser_js_file;
  365. RETURN_VALUE_IF_ERROR(temp_browser_js_file.Construct(m_file_name.CStr()), FALSE);
  366. if(!DOM_Environment::CheckBrowserJSSignature(temp_browser_js_file))
  367. {
  368. Console::WriteError(UNI_L("Browser js signature verification failed."));
  369. return FALSE;
  370. }
  371. return UpdatableFile::CheckResource();
  372. }
  373. OP_STATUS UpdatableBrowserJS::Cleanup()
  374. {
  375. FileDownloader::CleanUp();
  376. return DeleteDownloadedFile();
  377. }
  378. BOOL UpdatableBrowserJS::VerifyAttributes()
  379. {
  380. if (g_pcjs->GetIntegerPref(PrefsCollectionJS::BrowserJSSetting) <= 0)
  381. return FALSE;
  382. if (!HasAttrWithContent(URA_NAME))
  383. return FALSE;
  384. if (!HasAttrWithContent(URA_URL) && !HasAttrWithContent(URA_URLALT))
  385. return FALSE;
  386. if (!HasAttrWithContent(URA_TIMESTAMP))
  387. return FALSE;
  388. return TRUE;
  389. }
  390. OP_STATUS UpdatableDictionary::UpdateResource()
  391. {
  392. OpFile dictionary_file;
  393. OpString file_name;
  394. RETURN_IF_ERROR(GetAttrValue(URA_NAME, file_name));
  395. RETURN_IF_ERROR(dictionary_file.Construct(file_name, OPFILE_DICTIONARY_FOLDER));
  396. OpFile downloaded_file;
  397. RETURN_IF_ERROR(downloaded_file.Construct(m_file_name.CStr(), OPFILE_ABSOLUTE_FOLDER));
  398. RETURN_IF_ERROR(dictionary_file.CopyContents(&downloaded_file, FALSE));
  399. if (OpStatus::IsError(g_internal_spellcheck->RefreshInstalledLanguages()))
  400. return OpStatus::ERR;
  401. return OpStatus::OK;
  402. }
  403. BOOL UpdatableDictionary::CheckResource()
  404. {
  405. // Checksum test
  406. return UpdatableFile::CheckResource();
  407. }
  408. OP_STATUS UpdatableDictionary::Cleanup()
  409. {
  410. FileDownloader::CleanUp();
  411. return DeleteDownloadedFile();
  412. }
  413. BOOL UpdatableDictionary::VerifyAttributes()
  414. {
  415. if (!HasAttrWithContent(URA_NAME))
  416. return FALSE;
  417. if (!HasAttrWithContent(URA_URL) && !HasAttrWithContent(URA_URLALT))
  418. return FALSE;
  419. if (!HasAttrWithContent(URA_ID))
  420. return FALSE;
  421. return TRUE;
  422. }
  423. OP_STATUS UpdatableDictionaryXML::UpdateResource()
  424. {
  425. OpString file_name;
  426. OpFile dictionary_xml_file;
  427. OpFile downloaded_xml_file;
  428. int timestamp = 0;
  429. // Copy the file
  430. RETURN_IF_ERROR(GetAttrValue(URA_NAME, file_name));
  431. RETURN_IF_ERROR(dictionary_xml_file.Construct(file_name, OPFILE_DICTIONARY_FOLDER));
  432. RETURN_IF_ERROR(downloaded_xml_file.Construct(m_file_name.CStr(), OPFILE_ABSOLUTE_FOLDER));
  433. RETURN_IF_ERROR(dictionary_xml_file.CopyContents(&downloaded_xml_file, FALSE));
  434. // Write the timestamp
  435. RETURN_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp));
  436. TRAP_AND_RETURN(res, g_pcui->WriteIntegerL(PrefsCollectionUI::DictionaryTime, timestamp));
  437. TRAP_AND_RETURN(res, g_prefsManager->CommitL());
  438. return OpStatus::OK;
  439. }
  440. BOOL UpdatableDictionaryXML::CheckResource()
  441. {
  442. int timestamp;
  443. int current_timestamp = g_pcui->GetIntegerPref(PrefsCollectionUI::DictionaryTime);
  444. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp), FALSE);
  445. if(current_timestamp >= timestamp)
  446. {
  447. Console::WriteError(UNI_L("Invalid timestamp for dictionary file."));
  448. return FALSE;
  449. }
  450. // Checksum test
  451. return UpdatableFile::CheckResource();
  452. }
  453. OP_STATUS UpdatableDictionaryXML::Cleanup()
  454. {
  455. FileDownloader::CleanUp();
  456. return DeleteDownloadedFile();
  457. }
  458. BOOL UpdatableDictionaryXML::VerifyAttributes()
  459. {
  460. if (!HasAttrWithContent(URA_NAME))
  461. return FALSE;
  462. if (!HasAttrWithContent(URA_URL) && !HasAttrWithContent(URA_URLALT))
  463. return FALSE;
  464. if (!HasAttrWithContent(URA_TIMESTAMP))
  465. return FALSE;
  466. return TRUE;
  467. }
  468. #ifdef PLUGIN_AUTO_INSTALL
  469. UpdatablePlugin::UpdatablePlugin():
  470. m_async_process_runner(NULL)
  471. {
  472. // Need to have the process runner per platform
  473. # if defined(MSWIN)
  474. m_async_process_runner = OP_NEW(PIM_WindowsAsyncProcessRunner, ());
  475. # elif defined(_MACINTOSH_)
  476. m_async_process_runner = OP_NEW(PIM_MacAsyncProcessRunner, ());
  477. # else
  478. m_async_process_runner = NULL;
  479. // uncomment mock implementation in PluginInstallManager.h to use this:
  480. // m_async_process_runner = OP_NEW(PIM_MockAsyncProcessRunner, ());
  481. # endif // MSWIN
  482. if(m_async_process_runner)
  483. m_async_process_runner->SetListener(this);
  484. }
  485. UpdatablePlugin::~UpdatablePlugin()
  486. {
  487. if(m_async_process_runner)
  488. {
  489. m_async_process_runner->SetListener(NULL);
  490. OP_DELETE(m_async_process_runner);
  491. m_async_process_runner = NULL;
  492. }
  493. }
  494. void UpdatablePlugin::OnProcessFinished(DWORD exit_code)
  495. {
  496. OpString mime_type;
  497. RETURN_VOID_IF_ERROR(GetAttrValue(URA_MIME_TYPE, mime_type));
  498. if(0 == exit_code)
  499. g_plugin_install_manager->Notify(PIM_INSTALL_OK, mime_type);
  500. else
  501. g_plugin_install_manager->Notify(PIM_INSTALL_FAILED, mime_type);
  502. }
  503. OP_STATUS UpdatablePlugin::UpdateResource()
  504. {
  505. return OpStatus::ERR_NOT_SUPPORTED;
  506. }
  507. BOOL UpdatablePlugin::CheckResource()
  508. {
  509. /* DSK-336700:
  510. The autoupdate server can request two types of binary file verification here.
  511. If the XML with plugin information contains the <checksum> element, it's value is treated as a SHA-256 checksum hash of the
  512. file being verified and is compared with a hash calculated from the downloaded file.
  513. If the XML contains the <vendor-name> element, it's value is treated as a vendor name and is compared with the vendor name
  514. read from the digital signature of the file. The check is performed using the operating system API, see LaunchPI::VerifyExecutable().
  515. Warning:
  516. If both XML elements are present in the XML data sent from the server, the downloaded binary will be verified both ways and the final
  517. check result will only be TRUE if *both* verification methods return TRUE.
  518. If both XML elements are missing from the XML sent from the server, the file verification will FAIL. The file has to be verified with
  519. at least one verification method in order for this function to return TRUE.
  520. */
  521. OpString signature, vendor_name;
  522. OpStatus::Ignore(GetAttrValue(URA_CHECKSUM, signature));
  523. OpStatus::Ignore(GetAttrValue(URA_VENDOR_NAME, vendor_name));
  524. bool has_checksum = signature.HasContent()?true:false;
  525. bool has_vendor = vendor_name.HasContent()?true:false;
  526. // We need to be able to check at least one of them
  527. if (!has_checksum && !has_vendor)
  528. return false;
  529. if (has_checksum)
  530. {
  531. // Standard SHA-256 checksum test
  532. if (!UpdatableFile::CheckResource())
  533. // If the checksum was present and the check failed, don't try anything else but rather fail right away
  534. return false;
  535. // Continue to the vendor name check or return true right away if no vendor name has been sent from the server
  536. }
  537. if (has_vendor)
  538. {
  539. OpAutoPtr<LaunchPI> launch_pi(LaunchPI::Create());
  540. if (!launch_pi.get())
  541. // Something went terribly wrong
  542. return false;
  543. OpString target_filename;
  544. if (OpStatus::IsError(GetTargetFilename(target_filename)))
  545. return false;
  546. // If the vendor test fails then forget the true result that might have come from the checksum check
  547. if (!launch_pi->VerifyExecutable(target_filename.CStr(), vendor_name.CStr()))
  548. return false;
  549. }
  550. // At this point we know we have been sent at least one of the checksum and vendor XML elements and that no test
  551. // failed for the elements that have been sent.
  552. return true;
  553. }
  554. OP_STATUS UpdatablePlugin::Cleanup()
  555. {
  556. OP_STATUS ret = OpStatus::OK;
  557. FileDownloader::CleanUp();
  558. if(!m_file_name.IsEmpty())
  559. ret = DeleteDownloadedFile();
  560. return ret;
  561. }
  562. /***
  563. * Run the installer with or without the silent install_params.
  564. * The install_params string comes from the autoupdate server.
  565. */
  566. OP_STATUS UpdatablePlugin::InstallPlugin(BOOL a_silent)
  567. {
  568. if(NULL == m_async_process_runner)
  569. {
  570. OP_ASSERT(!"No async process runner for plugin");
  571. return OpStatus::ERR;
  572. }
  573. if(m_async_process_runner->IsRunning())
  574. {
  575. OP_ASSERT(!"Async process runner busy");
  576. return OpStatus::ERR;
  577. }
  578. OP_STATUS async_run_status;
  579. OpString install_params, empty_params;
  580. RETURN_IF_ERROR(GetAttrValue(URA_INSTALL_PARAMS, install_params));
  581. install_params.Strip();
  582. if(a_silent)
  583. {
  584. if(install_params.IsEmpty())
  585. return OpStatus::ERR;
  586. async_run_status = m_async_process_runner->RunProcess(m_file_name, install_params);
  587. }
  588. else
  589. async_run_status = m_async_process_runner->RunProcess(m_file_name, empty_params);
  590. return async_run_status;
  591. }
  592. OP_STATUS UpdatablePlugin::CancelPluginInstallation()
  593. {
  594. if (NULL == m_async_process_runner)
  595. {
  596. OP_ASSERT(!"No async process runner for plugin");
  597. return OpStatus::ERR;
  598. }
  599. if (!m_async_process_runner->IsRunning())
  600. {
  601. OP_ASSERT(!"Async process runner NOT busy - nothing to cancel really");
  602. return OpStatus::ERR;
  603. }
  604. // This is synchronous operation, we'll get the result right back
  605. return m_async_process_runner->KillProcess();
  606. }
  607. BOOL UpdatablePlugin::VerifyAttributes()
  608. {
  609. // List of mandatory attributes with a non-empty value
  610. // All values are stored as strings
  611. URAttr mandatory_attrs[] =
  612. {
  613. URA_TYPE,
  614. URA_MIME_TYPE,
  615. URA_HAS_INSTALLER
  616. };
  617. // List of attributes that must be present and non-empty when the plugin
  618. // has an installer
  619. URAttr mandatory_attrs_has_installer[] =
  620. {
  621. URA_NAME,
  622. URA_URL,
  623. URA_URLALT,
  624. URA_VERSION,
  625. URA_SIZE,
  626. URA_EULA_URL,
  627. URA_PLUGIN_NAME,
  628. URA_INSTALLS_SILENTLY
  629. };
  630. int mandatory_size = ARRAY_SIZE(mandatory_attrs);
  631. int installer_size = ARRAY_SIZE(mandatory_attrs_has_installer);
  632. for (int i=0; i<mandatory_size; i++)
  633. if (!HasAttrWithContent(mandatory_attrs[i]))
  634. return FALSE;
  635. bool has_installer;
  636. RETURN_VALUE_IF_ERROR(GetAttrValue(URA_HAS_INSTALLER, has_installer), FALSE);
  637. if (has_installer)
  638. {
  639. for (int i=0; i<installer_size; i++)
  640. if (!HasAttrWithContent(mandatory_attrs_has_installer[i]))
  641. return FALSE;
  642. // The plugin XML description must contain at least one of these
  643. if (!HasAttrWithContent(URA_CHECKSUM) && !HasAttrWithContent(URA_VENDOR_NAME))
  644. return FALSE;
  645. }
  646. return TRUE;
  647. }
  648. #endif // PLUGIN_AUTO_INSTALL
  649. OP_STATUS UpdatableHardwareBlocklist::UpdateResource()
  650. {
  651. OpString filename;
  652. RETURN_IF_ERROR(GetAttrValue(URA_NAME, filename));
  653. OpFile hardware_blocklist_file, downloaded_file;
  654. RETURN_IF_ERROR(downloaded_file.Construct(m_file_name, OPFILE_ABSOLUTE_FOLDER));
  655. RETURN_IF_ERROR(hardware_blocklist_file.Construct(filename, VEGA_BACKENDS_BLOCKLIST_FETCHED_FOLDER));
  656. RETURN_IF_ERROR(hardware_blocklist_file.CopyContents(&downloaded_file, FALSE));
  657. // Update the setting
  658. int timestamp = 0;
  659. RETURN_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp));
  660. if (timestamp > g_pcui->GetIntegerPref(PrefsCollectionUI::HardwareBlocklistTime)) {
  661. RETURN_IF_LEAVE(
  662. g_pcui->WriteIntegerL(PrefsCollectionUI::HardwareBlocklistTime, timestamp);
  663. g_prefsManager->CommitL();
  664. );
  665. }
  666. // Make sure we do not use a blocked web handler
  667. TrustedProtocolList list;
  668. RETURN_IF_ERROR(list.ResetBlockedWebHandlers());
  669. return OpStatus::OK;
  670. }
  671. BOOL UpdatableHardwareBlocklist::CheckResource()
  672. {
  673. // Checksum test
  674. if (!UpdatableFile::CheckResource())
  675. return FALSE;
  676. OpFile file;
  677. RETURN_VALUE_IF_ERROR(file.Construct(m_file_name.CStr()), FALSE);
  678. if (OpStatus::IsError(VEGABlocklistFile::CheckFile(&file)))
  679. {
  680. OpString target_filename;
  681. RETURN_VALUE_IF_ERROR(GetTargetFilename(target_filename), FALSE);
  682. OpString message;
  683. message.AppendFormat(UNI_L("Hardware blocklist %s failed to parse"), target_filename.CStr());
  684. Console::WriteError(message.CStr());
  685. return FALSE;
  686. }
  687. return TRUE;
  688. }
  689. OP_STATUS UpdatableHardwareBlocklist::Cleanup()
  690. {
  691. FileDownloader::CleanUp();
  692. return DeleteDownloadedFile();
  693. }
  694. BOOL UpdatableHardwareBlocklist::VerifyAttributes()
  695. {
  696. if (!HasAttrWithContent(URA_NAME))
  697. return FALSE;
  698. if (!HasAttrWithContent(URA_URL) && !HasAttrWithContent(URA_URLALT))
  699. return FALSE;
  700. if (!HasAttrWithContent(URA_TIMESTAMP))
  701. return FALSE;
  702. return TRUE;
  703. }
  704. OP_STATUS UpdatableHandlersIgnore::UpdateResource()
  705. {
  706. OpFile handlers_ignore_file, downloaded_file;
  707. RETURN_IF_ERROR(downloaded_file.Construct(m_file_name, OPFILE_ABSOLUTE_FOLDER));
  708. // Save to file specified by prefs as code elsewhere expects a file with that name
  709. OpFileFolder ignore;
  710. const uni_char* prefs_filename = 0;
  711. g_pcfiles->GetDefaultFilePref(PrefsCollectionFiles::HandlersIgnoreFile, &ignore, &prefs_filename);
  712. OpStringC filename = prefs_filename;
  713. if (filename.IsEmpty())
  714. return OpStatus::ERR;
  715. RETURN_IF_ERROR(handlers_ignore_file.Construct(filename, OPFILE_HOME_FOLDER));
  716. RETURN_IF_ERROR(handlers_ignore_file.CopyContents(&downloaded_file, FALSE));
  717. // Update the setting
  718. int timestamp = 0;
  719. RETURN_IF_ERROR(GetAttrValue(URA_TIMESTAMP, timestamp));
  720. if (timestamp > g_pcui->GetIntegerPref(PrefsCollectionUI::HandlersIgnoreTime)) {
  721. RETURN_IF_LEAVE(
  722. g_pcui->WriteIntegerL(PrefsCollectionUI::HandlersIgnoreTime, timestamp);
  723. g_prefsManager->CommitL();
  724. );
  725. }
  726. return OpStatus::OK;
  727. }
  728. OP_STATUS UpdatableHandlersIgnore::Cleanup()
  729. {
  730. FileDownloader::CleanUp();
  731. return DeleteDownloadedFile();
  732. }
  733. BOOL UpdatableHandlersIgnore::VerifyAttributes()
  734. {
  735. if (!HasAttrWithContent(URA_NAME))
  736. return FALSE;
  737. if (!HasAttrWithContent(URA_URL))
  738. return FALSE;
  739. if (!HasAttrWithContent(URA_TIMESTAMP))
  740. return FALSE;
  741. return TRUE;
  742. }
  743. #endif // AUTO_UPDATE_SUPPORT