FileLocation.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "FileLocation.h"
  6. #include "nsZipArchive.h"
  7. #include "nsURLHelper.h"
  8. namespace mozilla {
  9. FileLocation::FileLocation()
  10. {
  11. }
  12. FileLocation::~FileLocation()
  13. {
  14. }
  15. FileLocation::FileLocation(nsIFile* aFile)
  16. {
  17. Init(aFile);
  18. }
  19. FileLocation::FileLocation(nsIFile* aFile, const char* aPath)
  20. {
  21. Init(aFile, aPath);
  22. }
  23. FileLocation::FileLocation(const FileLocation& aFile, const char* aPath)
  24. {
  25. if (aFile.IsZip()) {
  26. if (aFile.mBaseFile) {
  27. Init(aFile.mBaseFile, aFile.mPath.get());
  28. }
  29. else {
  30. Init(aFile.mBaseZip, aFile.mPath.get());
  31. }
  32. if (aPath) {
  33. int32_t i = mPath.RFindChar('/');
  34. if (kNotFound == i) {
  35. mPath.Truncate(0);
  36. } else {
  37. mPath.Truncate(i + 1);
  38. }
  39. mPath += aPath;
  40. }
  41. } else {
  42. if (aPath) {
  43. nsCOMPtr<nsIFile> cfile;
  44. aFile.mBaseFile->GetParent(getter_AddRefs(cfile));
  45. #if defined(XP_WIN)
  46. nsAutoCString pathStr(aPath);
  47. char* p;
  48. uint32_t len = pathStr.GetMutableData(&p);
  49. for (; len; ++p, --len) {
  50. if ('/' == *p) {
  51. *p = '\\';
  52. }
  53. }
  54. cfile->AppendRelativeNativePath(pathStr);
  55. #else
  56. cfile->AppendRelativeNativePath(nsDependentCString(aPath));
  57. #endif
  58. Init(cfile);
  59. } else {
  60. Init(aFile.mBaseFile);
  61. }
  62. }
  63. }
  64. void
  65. FileLocation::Init(nsIFile* aFile)
  66. {
  67. mBaseZip = nullptr;
  68. mBaseFile = aFile;
  69. mPath.Truncate();
  70. }
  71. void
  72. FileLocation::Init(nsIFile* aFile, const char* aPath)
  73. {
  74. mBaseZip = nullptr;
  75. mBaseFile = aFile;
  76. mPath = aPath;
  77. }
  78. void
  79. FileLocation::Init(nsZipArchive* aZip, const char* aPath)
  80. {
  81. mBaseZip = aZip;
  82. mBaseFile = nullptr;
  83. mPath = aPath;
  84. }
  85. void
  86. FileLocation::GetURIString(nsACString& aResult) const
  87. {
  88. if (mBaseFile) {
  89. net_GetURLSpecFromActualFile(mBaseFile, aResult);
  90. } else if (mBaseZip) {
  91. RefPtr<nsZipHandle> handler = mBaseZip->GetFD();
  92. handler->mFile.GetURIString(aResult);
  93. }
  94. if (IsZip()) {
  95. aResult.Insert("jar:", 0);
  96. aResult += "!/";
  97. aResult += mPath;
  98. }
  99. }
  100. already_AddRefed<nsIFile>
  101. FileLocation::GetBaseFile()
  102. {
  103. if (IsZip() && mBaseZip) {
  104. RefPtr<nsZipHandle> handler = mBaseZip->GetFD();
  105. if (handler) {
  106. return handler->mFile.GetBaseFile();
  107. }
  108. return nullptr;
  109. }
  110. nsCOMPtr<nsIFile> file = mBaseFile;
  111. return file.forget();
  112. }
  113. bool
  114. FileLocation::Equals(const FileLocation& aFile) const
  115. {
  116. if (mPath != aFile.mPath) {
  117. return false;
  118. }
  119. if (mBaseFile && aFile.mBaseFile) {
  120. bool eq;
  121. return NS_SUCCEEDED(mBaseFile->Equals(aFile.mBaseFile, &eq)) && eq;
  122. }
  123. const FileLocation* a = this;
  124. const FileLocation* b = &aFile;
  125. if (a->mBaseZip) {
  126. RefPtr<nsZipHandle> handler = a->mBaseZip->GetFD();
  127. a = &handler->mFile;
  128. }
  129. if (b->mBaseZip) {
  130. RefPtr<nsZipHandle> handler = b->mBaseZip->GetFD();
  131. b = &handler->mFile;
  132. }
  133. return a->Equals(*b);
  134. }
  135. nsresult
  136. FileLocation::GetData(Data& aData)
  137. {
  138. if (!IsZip()) {
  139. return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &aData.mFd.rwget());
  140. }
  141. aData.mZip = mBaseZip;
  142. if (!aData.mZip) {
  143. aData.mZip = new nsZipArchive();
  144. aData.mZip->OpenArchive(mBaseFile);
  145. }
  146. aData.mItem = aData.mZip->GetItem(mPath.get());
  147. if (aData.mItem) {
  148. return NS_OK;
  149. }
  150. return NS_ERROR_FILE_UNRECOGNIZED_PATH;
  151. }
  152. nsresult
  153. FileLocation::Data::GetSize(uint32_t* aResult)
  154. {
  155. if (mFd) {
  156. PRFileInfo64 fileInfo;
  157. if (PR_SUCCESS != PR_GetOpenFileInfo64(mFd, &fileInfo)) {
  158. return NS_ErrorAccordingToNSPR();
  159. }
  160. if (fileInfo.size > int64_t(UINT32_MAX)) {
  161. return NS_ERROR_FILE_TOO_BIG;
  162. }
  163. *aResult = fileInfo.size;
  164. return NS_OK;
  165. }
  166. else if (mItem) {
  167. *aResult = mItem->RealSize();
  168. return NS_OK;
  169. }
  170. return NS_ERROR_NOT_INITIALIZED;
  171. }
  172. nsresult
  173. FileLocation::Data::Copy(char* aBuf, uint32_t aLen)
  174. {
  175. if (mFd) {
  176. for (uint32_t totalRead = 0; totalRead < aLen;) {
  177. int32_t read = PR_Read(mFd, aBuf + totalRead,
  178. XPCOM_MIN(aLen - totalRead, uint32_t(INT32_MAX)));
  179. if (read < 0) {
  180. return NS_ErrorAccordingToNSPR();
  181. }
  182. totalRead += read;
  183. }
  184. return NS_OK;
  185. }
  186. else if (mItem) {
  187. nsZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t*>(aBuf),
  188. aLen, true);
  189. uint32_t readLen;
  190. cursor.Copy(&readLen);
  191. if (readLen != aLen) {
  192. nsZipArchive::sFileCorruptedReason = "FileLocation::Data: insufficient data";
  193. return NS_ERROR_FILE_CORRUPTED;
  194. }
  195. return NS_OK;
  196. }
  197. return NS_ERROR_NOT_INITIALIZED;
  198. }
  199. } /* namespace mozilla */