sbURIPropertyInfo.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 #include "sbURIPropertyInfo.h"
28 
29 #include <nsAutoPtr.h>
30 #include <nsIFileURL.h>
31 
32 #include <nsServiceManagerUtils.h>
33 #include <nsNetUtil.h>
34 
35 #include <sbLockUtils.h>
36 
39 
40 NS_INTERFACE_TABLE_HEAD(sbURIPropertyInfo)
41 NS_INTERFACE_TABLE_BEGIN
42 NS_INTERFACE_TABLE_ENTRY(sbURIPropertyInfo, sbIURIPropertyInfo)
43 NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(sbURIPropertyInfo, sbIPropertyInfo, sbIURIPropertyInfo)
44 NS_INTERFACE_TABLE_END
45 NS_INTERFACE_TABLE_TAIL_INHERITING(sbPropertyInfo)
46 
47 sbURIPropertyInfo::sbURIPropertyInfo()
48 : mURISchemeConstraintLock(nsnull)
49 , mIOServiceLock(nsnull)
50 {
51  mType = NS_LITERAL_STRING("uri");
52 
53  mURISchemeConstraintLock = PR_NewLock();
54  NS_ASSERTION(mURISchemeConstraintLock,
55  "sbURIPropertyInfo::mURISchemeConstraintLock failed to create lock!");
56 
57  mIOServiceLock = PR_NewLock();
58  NS_ASSERTION(mIOServiceLock,
59  "sbURIPropertyInfo::mIOServiceLock failed to create lock!");
60 }
61 
63 {
64  if(mURISchemeConstraintLock) {
65  PR_DestroyLock(mURISchemeConstraintLock);
66  }
67 }
68 
69 nsresult
71 {
72  nsresult rv;
73 
74  rv = sbPropertyInfo::Init();
75  NS_ENSURE_SUCCESS(rv, rv);
76 
77  rv = InitializeOperators();
78  NS_ENSURE_SUCCESS(rv, rv);
79 
80  return NS_OK;
81 }
82 
83 nsresult
84 sbURIPropertyInfo::InitializeOperators()
85 {
86  nsresult rv;
87  nsAutoString op;
88  nsRefPtr<sbPropertyOperator> propOp;
89 
90  rv = sbPropertyInfo::GetOPERATOR_CONTAINS(op);
91  NS_ENSURE_SUCCESS(rv, rv);
92  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.contains"));
93  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
94  rv = mOperators.AppendObject(propOp);
95  NS_ENSURE_SUCCESS(rv, rv);
96 
97  rv = sbPropertyInfo::GetOPERATOR_NOTCONTAINS(op);
98  NS_ENSURE_SUCCESS(rv, rv);
99  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.not_contain"));
100  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
101  rv = mOperators.AppendObject(propOp);
102  NS_ENSURE_SUCCESS(rv, rv);
103 
104  rv = sbPropertyInfo::GetOPERATOR_EQUALS(op);
105  NS_ENSURE_SUCCESS(rv, rv);
106  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.is"));
107  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
108  rv = mOperators.AppendObject(propOp);
109  NS_ENSURE_SUCCESS(rv, rv);
110 
111  rv = sbPropertyInfo::GetOPERATOR_NOTEQUALS(op);
112  NS_ENSURE_SUCCESS(rv, rv);
113  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.is_not"));
114  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
115  rv = mOperators.AppendObject(propOp);
116  NS_ENSURE_SUCCESS(rv, rv);
117 
118  rv = sbPropertyInfo::GetOPERATOR_BEGINSWITH(op);
119  NS_ENSURE_SUCCESS(rv, rv);
120  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.starts"));
121  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
122  rv = mOperators.AppendObject(propOp);
123  NS_ENSURE_SUCCESS(rv, rv);
124 
125  rv = sbPropertyInfo::GetOPERATOR_NOTBEGINSWITH(op);
126  NS_ENSURE_SUCCESS(rv, rv);
127  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.not_start"));
128  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
129  rv = mOperators.AppendObject(propOp);
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  rv = sbPropertyInfo::GetOPERATOR_ENDSWITH(op);
133  NS_ENSURE_SUCCESS(rv, rv);
134  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.ends"));
135  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
136  rv = mOperators.AppendObject(propOp);
137  NS_ENSURE_SUCCESS(rv, rv);
138 
139  rv = sbPropertyInfo::GetOPERATOR_NOTENDSWITH(op);
140  NS_ENSURE_SUCCESS(rv, rv);
141  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.not_end"));
142  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
143  rv = mOperators.AppendObject(propOp);
144  NS_ENSURE_SUCCESS(rv, rv);
145 
146  return NS_OK;
147 }
148 
149 NS_IMETHODIMP sbURIPropertyInfo::Validate(const nsAString & aValue, PRBool *_retval)
150 {
151  NS_ENSURE_ARG_POINTER(_retval);
152  *_retval = PR_TRUE;
153 
154  nsresult rv = EnsureIOService();
155  NS_ENSURE_SUCCESS(rv, rv);
156 
157  nsCOMPtr<nsIURI> uri;
158  rv = NS_NewURI(getter_AddRefs(uri), aValue, nsnull, nsnull, mIOService);
159  if(NS_FAILED(rv)) {
160  *_retval = PR_FALSE;
161  return NS_OK;
162  }
163 
164  sbSimpleAutoLock lock(mURISchemeConstraintLock);
165  if(!mURISchemeConstraint.IsEmpty()) {
166  NS_ConvertUTF16toUTF8 narrow(mURISchemeConstraint);
167  PRBool valid = PR_FALSE;
168 
169  rv = uri->SchemeIs(narrow.get(), &valid);
170  NS_ENSURE_SUCCESS(rv, rv);
171 
172  if(!valid) {
173  *_retval = PR_FALSE;
174  }
175  }
176 
177  return NS_OK;
178 }
179 
180 NS_IMETHODIMP sbURIPropertyInfo::Sanitize(const nsAString & aValue, nsAString & _retval)
181 {
182  return NS_ERROR_NOT_IMPLEMENTED;
183 }
184 
185 PRBool sbURIPropertyInfo::IsInvalidEmpty(const nsAString &aValue) {
186  // search for ":", ":/" and "://" with no trailing chars
187  if (aValue.IsEmpty())
188  return PR_FALSE;
189 
190  PRUint32 pos = aValue.FindChar(':');
191  if (pos < 0)
192  return PR_FALSE;
193  if (pos == aValue.Length()-1 ||
194  (pos == aValue.Length()-2 && aValue.CharAt(pos + 1) == '/') ||
195  (pos == aValue.Length()-3 && aValue.CharAt(pos + 1) == '/' && aValue.CharAt(pos + 2) == '/')) {
196  return PR_TRUE;
197  }
198  return PR_FALSE;
199 }
200 
201 NS_IMETHODIMP sbURIPropertyInfo::Format(const nsAString & aValue, nsAString & _retval)
202 {
203  if (aValue.IsVoid()) {
204  _retval.Truncate();
205  return NS_OK;
206  }
207 
208  nsresult rv;
209  nsCString escapedSpec;
210 
211  if (!IsInvalidEmpty(aValue)) {
212  rv = EnsureIOService();
213  NS_ENSURE_SUCCESS(rv, rv);
214 
215  nsCOMPtr<nsIURI> uri;
216  rv = NS_NewURI(getter_AddRefs(uri), aValue, nsnull, nsnull, mIOService);
217  NS_ENSURE_SUCCESS(rv, rv);
218 
219  {
220  // Unlock when we're done with mURISchemeConstraint.
221  sbSimpleAutoLock lock(mURISchemeConstraintLock);
222  if (!mURISchemeConstraint.IsEmpty()) {
223  NS_ConvertUTF16toUTF8 narrow(mURISchemeConstraint);
224  PRBool valid = PR_FALSE;
225 
226  rv = uri->SchemeIs(narrow.get(), &valid);
227  NS_ENSURE_SUCCESS(rv, rv);
228 
229  if (!valid) {
230  return NS_ERROR_FAILURE;
231  }
232  }
233  }
234 
235  nsCOMPtr<nsIFileURL> url = do_QueryInterface(uri, &rv);
236  if (NS_SUCCEEDED(rv)) {
237  // Get the file path from file url
238  nsCOMPtr<nsIFile> file;
239  rv = url->GetFile(getter_AddRefs(file));
240  NS_ENSURE_SUCCESS(rv, rv);
241 
242  nsString path;
243  rv = file->GetPath(path);
244  NS_ENSURE_SUCCESS(rv, rv);
245  // path won't be escaped.
246  _retval = path;
247  return NS_OK;
248  } else {
249  rv = uri->GetSpec(escapedSpec);
250  NS_ENSURE_SUCCESS(rv, rv);
251  }
252  } else {
253  CopyUTF16toUTF8(aValue, escapedSpec);
254  }
255 
256  nsCOMPtr<nsINetUtil> netUtil =
257  do_GetService("@mozilla.org/network/util;1", &rv);
258  NS_ENSURE_SUCCESS(rv, rv);
259 
260  // Unescape the spec for display purposes.
261  nsCString unescapedSpec;
262  rv = netUtil->UnescapeString(escapedSpec,
263  nsINetUtil::ESCAPE_ALL,
264  unescapedSpec);
265  NS_ENSURE_SUCCESS(rv, rv);
266 
267  // Encode bidirectional formatting characters.
268  // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
269 
270  PRInt32 offset = 0;
271  char buffer[] = {'%','E','2','%','8','0','%','x','x'}; //escaped string
272  while ((offset = unescapedSpec.Find(NS_LITERAL_CSTRING("\xE2\x80"), offset)) != -1) {
273  switch ((PRUint8)unescapedSpec[offset + 2]) {
274  case 0x8E: // U+200E
275  case 0x8F: // U+200F
276  buffer[7] = '8';
277  buffer[8] = unescapedSpec[offset + 2] - 0x48;
278  break;
279  case 0xAA: // U+202A
280  case 0xAB: // U+202B
281  case 0xAC: // U+202C
282  case 0xAD: // U+202D
283  case 0xAE: // U+202E
284  buffer[7] = 'A';
285  buffer[8] = unescapedSpec[offset + 2] - 0x5F;
286  break;
287  default:
288  offset += 2; // skip over this occurrence, not a character we want
289  continue;
290  }
291  unescapedSpec.Replace(offset, 3, buffer, sizeof(buffer));
292  }
293 
294  CopyUTF8toUTF16(unescapedSpec, _retval);
295 
296  return NS_OK;
297 }
298 
299 NS_IMETHODIMP sbURIPropertyInfo::MakeSearchable(const nsAString & aValue, nsAString & _retval)
300 {
301  _retval = EmptyString();
302  return NS_OK;
303 }
304 
305 // We provide this implementation because the base class calls
306 // MakeSearchable to find the MakeSortable value and though
307 // we don't want URIs to be searchable, we still want to sort them.
308 NS_IMETHODIMP sbURIPropertyInfo::MakeSortable(const nsAString & aValue, nsAString & _retval)
309 {
310  nsresult rv;
311 
312  if (!IsInvalidEmpty(aValue)) {
313  rv = EnsureIOService();
314  NS_ENSURE_SUCCESS(rv, rv);
315 
316  nsCOMPtr<nsIURI> uri;
317  rv = NS_NewURI(getter_AddRefs(uri), aValue, nsnull, nsnull, mIOService);
318  NS_ENSURE_SUCCESS(rv, rv);
319 
320  // Get file path
321  nsCAutoString spec;
322  rv = uri->GetSpec(spec);
323  NS_ENSURE_SUCCESS(rv, rv);
324 
325  nsCOMPtr<nsILocalFile> localFile =
326  do_CreateInstance("@mozilla.org/file/local;1", &rv);
327  NS_ENSURE_SUCCESS(rv, rv);
328  rv = localFile->InitWithPath(NS_ConvertUTF8toUTF16(spec));
329  if (NS_SUCCEEDED(rv)) {
330  // MakeSortable is called by smart playlist builder. The return value
331  // will be compared with the top level property contentURL.
332  // So update file path to file url so it can be matched.
333  nsCOMPtr<nsIFile> file = do_QueryInterface(localFile, &rv);
334  NS_ENSURE_SUCCESS(rv, rv);
335  nsCOMPtr<nsIURI> fileUri;
336  rv = mIOService->NewFileURI(file, getter_AddRefs(fileUri));
337  NS_ENSURE_SUCCESS(rv, rv);
338 
339  nsCAutoString escapedSpec;
340  rv = fileUri->GetSpec(escapedSpec);
341  NS_ENSURE_SUCCESS(rv, rv);
342 
343  // Need to unescape the value after URI tweak.
344  nsCOMPtr<nsINetUtil> netUtil =
345  do_GetService("@mozilla.org/network/util;1", &rv);
346  NS_ENSURE_SUCCESS(rv, rv);
347  rv = netUtil->UnescapeString(escapedSpec,
348  nsINetUtil::ESCAPE_ALL,
349  spec);
350  NS_ENSURE_SUCCESS(rv, rv);
351  }
352 
353  NS_ConvertUTF8toUTF16 wide(spec);
354  _retval = wide;
355  } else {
356  _retval = aValue;
357  }
358 
359  return NS_OK;
360 }
361 
362 NS_IMETHODIMP sbURIPropertyInfo::GetConstrainScheme(nsAString & aConstrainScheme)
363 {
364  sbSimpleAutoLock lock(mURISchemeConstraintLock);
365  aConstrainScheme = mURISchemeConstraint;
366  return NS_OK;
367 }
368 NS_IMETHODIMP sbURIPropertyInfo::SetConstrainScheme(const nsAString & aConstrainScheme)
369 {
370  sbSimpleAutoLock lock(mURISchemeConstraintLock);
371 
372  if(mURISchemeConstraint.IsEmpty()) {
373  mURISchemeConstraint = aConstrainScheme;
374  return NS_OK;
375  }
376 
377  return NS_ERROR_ALREADY_INITIALIZED;
378 }
379 
381 {
382  nsresult rv = NS_OK;
383 
384  if(!mIOService) {
385  mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
386  }
387 
388  return rv;
389 }
return NS_OK
_dialogDatepicker pos
onPageChanged aValue
Definition: FeedWriter.js:1395
NS_IMETHOD Validate(const nsAString &aValue, PRBool *_retval)
The property information specific to URL/URI fields.
PRUint32 & offset
PRBool IsInvalidEmpty(const nsAString &aValue)
NS_IMETHOD Sanitize(const nsAString &aValue, nsAString &_retval)
NS_IMPL_ADDREF_INHERITED(sbURIPropertyInfo, sbPropertyInfo)
An interface used to describe a metadata property for use by the UI and other sbILibrary interfaces (...
NS_IMETHOD Format(const nsAString &aValue, nsAString &_retval)
NS_IMETHOD EnsureIOService()
NS_IMETHOD MakeSortable(const nsAString &aValue, nsAString &_retval)
NS_IMPL_RELEASE_INHERITED(sbURIPropertyInfo, sbPropertyInfo)
function url(spec)
var uri
Definition: FeedWriter.js:1135
nsCOMArray< sbIPropertyOperator > mOperators
NS_IMETHOD MakeSearchable(const nsAString &aValue, nsAString &_retval)
var file