1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Mozilla code
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Mozilla Foundation
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Mike Hommey <mh@glandium.org>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "FileLocation.h"
39 : #include "nsZipArchive.h"
40 : #include "nsURLHelper.h"
41 :
42 : namespace mozilla {
43 :
44 759444 : FileLocation::FileLocation(const FileLocation &file, const char *path)
45 : {
46 759444 : if (file.IsZip()) {
47 16 : if (file.mBaseFile) {
48 16 : Init(file.mBaseFile, file.mPath.get());
49 : } else {
50 0 : Init(file.mBaseZip, file.mPath.get());
51 : }
52 16 : if (path) {
53 3 : PRInt32 i = mPath.RFindChar('/');
54 3 : if (kNotFound == i) {
55 2 : mPath.Truncate(0);
56 : } else {
57 1 : mPath.Truncate(i + 1);
58 : }
59 3 : mPath += path;
60 : }
61 : } else {
62 759428 : if (path) {
63 909654 : nsCOMPtr<nsIFile> cfile;
64 454827 : file.mBaseFile->GetParent(getter_AddRefs(cfile));
65 909654 : nsCOMPtr<nsILocalFile> clfile = do_QueryInterface(cfile);
66 :
67 : #if defined(XP_WIN) || defined(XP_OS2)
68 : nsCAutoString pathStr(path);
69 : char *p;
70 : PRUint32 len = pathStr.GetMutableData(&p);
71 : for (; len; ++p, --len) {
72 : if ('/' == *p) {
73 : *p = '\\';
74 : }
75 : }
76 : clfile->AppendRelativeNativePath(pathStr);
77 : #else
78 454827 : clfile->AppendRelativeNativePath(nsDependentCString(path));
79 : #endif
80 454827 : Init(clfile);
81 : } else {
82 304601 : Init(file.mBaseFile);
83 : }
84 : }
85 759444 : }
86 :
87 : void
88 166131 : FileLocation::GetURIString(nsACString &result) const
89 : {
90 166131 : if (mBaseFile) {
91 166131 : net_GetURLSpecFromActualFile(mBaseFile, result);
92 0 : } else if (mBaseZip) {
93 0 : nsRefPtr<nsZipHandle> handler = mBaseZip->GetFD();
94 0 : handler->mFile.GetURIString(result);
95 : }
96 166131 : if (IsZip()) {
97 9 : result.Insert("jar:", 0);
98 9 : result += "!/";
99 9 : result += mPath;
100 : }
101 166131 : }
102 :
103 : already_AddRefed<nsILocalFile>
104 7743 : FileLocation::GetBaseFile()
105 : {
106 7743 : if (IsZip() && mBaseZip) {
107 0 : nsRefPtr<nsZipHandle> handler = mBaseZip->GetFD();
108 0 : if (handler)
109 0 : return handler->mFile.GetBaseFile();
110 0 : return NULL;
111 : }
112 :
113 15486 : nsCOMPtr<nsILocalFile> file = mBaseFile;
114 7743 : return file.forget();
115 : }
116 :
117 : bool
118 203 : FileLocation::Equals(const FileLocation &file) const
119 : {
120 203 : if (mPath != file.mPath)
121 0 : return false;
122 :
123 203 : if (mBaseFile && file.mBaseFile) {
124 : bool eq;
125 203 : return NS_SUCCEEDED(mBaseFile->Equals(file.mBaseFile, &eq)) && eq;
126 : }
127 :
128 0 : const FileLocation *a = this, *b = &file;
129 0 : if (a->mBaseZip) {
130 0 : nsRefPtr<nsZipHandle> handler = a->mBaseZip->GetFD();
131 0 : a = &handler->mFile;
132 : }
133 0 : if (b->mBaseZip) {
134 0 : nsRefPtr<nsZipHandle> handler = b->mBaseZip->GetFD();
135 0 : b = &handler->mFile;
136 : }
137 0 : return a->Equals(*b);
138 : }
139 :
140 : nsresult
141 317791 : FileLocation::GetData(Data &data)
142 : {
143 317791 : if (!IsZip()) {
144 317680 : return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &data.mFd);
145 : }
146 111 : data.mZip = mBaseZip;
147 111 : if (!data.mZip) {
148 111 : data.mZip = new nsZipArchive();
149 111 : data.mZip->OpenArchive(mBaseFile);
150 : }
151 111 : data.mItem = data.mZip->GetItem(mPath.get());
152 111 : if (data.mItem)
153 6 : return NS_OK;
154 105 : return NS_ERROR_FILE_UNRECOGNIZED_PATH;
155 : }
156 :
157 : nsresult
158 317579 : FileLocation::Data::GetSize(PRUint32 *result)
159 : {
160 317579 : if (mFd) {
161 : PRFileInfo64 fileInfo;
162 317573 : if (PR_SUCCESS != PR_GetOpenFileInfo64(mFd, &fileInfo))
163 0 : return NS_ErrorAccordingToNSPR();
164 :
165 317573 : if (fileInfo.size > PRInt64(PR_UINT32_MAX))
166 0 : return NS_ERROR_FILE_TOO_BIG;
167 :
168 317573 : *result = fileInfo.size;
169 317573 : return NS_OK;
170 6 : } else if (mItem) {
171 6 : *result = mItem->RealSize();
172 6 : return NS_OK;
173 : }
174 0 : return NS_ERROR_NOT_INITIALIZED;
175 : }
176 :
177 : nsresult
178 317579 : FileLocation::Data::Copy(char *buf, PRUint32 len)
179 : {
180 317579 : if (mFd) {
181 952719 : for (PRUint32 totalRead = 0; totalRead < len; ) {
182 317573 : PRInt32 read = PR_Read(mFd, buf + totalRead, NS_MIN(len - totalRead, PRUint32(PR_INT32_MAX)));
183 317573 : if (read < 0)
184 0 : return NS_ErrorAccordingToNSPR();
185 317573 : totalRead += read;
186 : }
187 317573 : return NS_OK;
188 6 : } else if (mItem) {
189 12 : nsZipCursor cursor(mItem, mZip, reinterpret_cast<PRUint8 *>(buf), len, true);
190 : PRUint32 readLen;
191 6 : cursor.Copy(&readLen);
192 6 : return (readLen == len) ? NS_OK : NS_ERROR_FILE_CORRUPTED;
193 : }
194 0 : return NS_ERROR_NOT_INITIALIZED;
195 : }
196 :
197 : } /* namespace mozilla */
|