source: trunk/third/mozilla/caps/src/nsPrincipal.cpp @ 22325

Revision 22325, 22.1 KB checked in by rbasch, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22324, which included commits to RCS files with non-trunk default branches.
  • Property svn:executable set to *
Line 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *   Christopher A. Aillon <christopher@aillon.com>
24 *   Giorgio Maone <g.maone@informaction.com>
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40#include "nscore.h"
41#include "nsScriptSecurityManager.h"
42#include "nsString.h"
43#include "nsReadableUtils.h"
44#include "plstr.h"
45#include "nsCRT.h"
46#include "nsIURI.h"
47#include "nsNetUtil.h"
48#include "nsJSPrincipals.h"
49#include "nsVoidArray.h"
50#include "nsHashtable.h"
51#include "nsIObjectInputStream.h"
52#include "nsIObjectOutputStream.h"
53#include "nsIPrefBranch.h"
54#include "nsIPrefService.h"
55
56#include "nsPrincipal.h"
57
58
59// Static member variables
60PRInt32 nsPrincipal::sCapabilitiesOrdinal = 0;
61const char nsPrincipal::sInvalid[] = "Invalid";
62
63
64NS_INTERFACE_MAP_BEGIN(nsPrincipal)
65  NS_INTERFACE_MAP_ENTRY(nsIPrincipal)
66  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISerializable, nsIPrincipal)
67  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrincipal)
68  NS_INTERFACE_MAP_ENTRY(nsISubsumingPrincipal)
69  NS_INTERFACE_MAP_ENTRY(nsIPrincipalObsolete)
70  NS_IMPL_QUERY_CLASSINFO(nsPrincipal)
71NS_INTERFACE_MAP_END
72
73NS_IMPL_CI_INTERFACE_GETTER3(nsPrincipal,
74                             nsISubsumingPrincipal,
75                             nsIPrincipal,
76                             nsISerializable)
77
78NS_IMETHODIMP_(nsrefcnt)
79nsPrincipal::AddRef()
80{
81  NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt");
82  // XXXcaa does this need to be threadsafe?  See bug 143559.
83  nsrefcnt count = PR_AtomicIncrement((PRInt32 *)&mJSPrincipals.refcount);
84  NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this));
85  return count;
86}
87
88NS_IMETHODIMP_(nsrefcnt)
89nsPrincipal::Release()
90{
91  NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release");
92  nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
93  NS_LOG_RELEASE(this, count, "nsPrincipal");
94  if (count == 0) {
95    NS_DELETEXPCOM(this);
96  }
97
98  return count;
99}
100
101nsPrincipal::nsPrincipal()
102  : mCapabilities(7),
103    mSecurityPolicy(nsnull),
104    mTrusted(PR_FALSE),
105    mInitialized(PR_FALSE)
106{
107}
108
109nsresult
110nsPrincipal::Init(const char *aCertID, nsIURI *aCodebase)
111{
112  NS_ENSURE_STATE(!mInitialized);
113  NS_ENSURE_ARG_POINTER(aCertID || aCodebase); // better have one of these.
114
115  mInitialized = PR_TRUE;
116
117  mCodebase = aCodebase;
118
119  nsresult rv;
120  if (aCertID) {
121    rv = SetCertificate(aCertID, nsnull);
122    if (NS_SUCCEEDED(rv)) {
123      rv = mJSPrincipals.Init(this, aCertID);
124    }
125  }
126  else {
127    nsCAutoString spec;
128    rv = mCodebase->GetSpec(spec);
129    if (NS_SUCCEEDED(rv)) {
130      rv = mJSPrincipals.Init(this, spec.get());
131    }
132  }
133
134  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "nsPrincipal::Init() failed");
135
136  return rv;
137}
138
139
140PR_STATIC_CALLBACK(PRBool)
141deleteElement(void* aElement, void *aData)
142{
143  nsHashtable *ht = (nsHashtable *) aElement;
144  delete ht;
145  return PR_TRUE;
146}
147
148nsPrincipal::~nsPrincipal(void)
149{
150  mAnnotations.EnumerateForwards(deleteElement, nsnull);
151  SetSecurityPolicy(nsnull);
152}
153
154NS_IMETHODIMP
155nsPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin)
156{
157  NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitalized!");
158
159  JSPRINCIPALS_HOLD(cx, &mJSPrincipals);
160  *jsprin = &mJSPrincipals;
161  return NS_OK;
162}
163
164NS_IMETHODIMP
165nsPrincipal::GetOrigin(char **aOrigin)
166{
167  *aOrigin = nsnull;
168
169  nsIURI* uri = mDomain ? mDomain : mCodebase;
170  if (!uri) {
171    NS_ASSERTION(mCert, "No Domain or Codebase for a non-cert principal");
172    return NS_ERROR_FAILURE;
173  }
174
175  nsCAutoString hostPort;
176
177  // chrome: URLs don't have a meaningful origin, so make
178  // sure we just get the full spec for them.
179  // XXX this should be removed in favor of the solution in
180  // bug 160042.
181  PRBool isChrome;
182  nsresult rv = uri->SchemeIs("chrome", &isChrome);
183  if (NS_SUCCEEDED(rv) && !isChrome) {
184    rv = uri->GetHostPort(hostPort);
185  }
186
187  if (NS_SUCCEEDED(rv) && !isChrome) {
188    nsCAutoString scheme;
189    rv = uri->GetScheme(scheme);
190    NS_ENSURE_SUCCESS(rv, rv);
191    *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort);
192  }
193  else {
194    // Some URIs (e.g., nsSimpleURI) don't support host. Just
195    // get the full spec.
196    nsCAutoString spec;
197    rv = uri->GetSpec(spec);
198    NS_ENSURE_SUCCESS(rv, rv);
199    *aOrigin = ToNewCString(spec);
200  }
201
202  return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
203}
204
205NS_IMETHODIMP
206nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy)
207{
208  if (mSecurityPolicy && mSecurityPolicy->IsInvalid())
209    SetSecurityPolicy(nsnull);
210 
211  *aSecurityPolicy = (void *) mSecurityPolicy;
212  return NS_OK;
213}
214
215NS_IMETHODIMP
216nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
217{
218  DomainPolicy *newPolicy = NS_REINTERPRET_CAST(
219                              DomainPolicy *, aSecurityPolicy);
220  if (newPolicy)
221    newPolicy->Hold();
222 
223  if (mSecurityPolicy)
224    mSecurityPolicy->Drop();
225 
226  mSecurityPolicy = newPolicy;
227  return NS_OK;
228}
229
230NS_IMETHODIMP
231nsPrincipal::Equals(nsIPrincipal *aOther, PRBool *aResult)
232{
233  *aResult = PR_FALSE;
234
235  if (!aOther) {
236    NS_WARNING("Need a principal to compare this to!");
237    return NS_OK;
238  }
239
240  if (this != aOther) {
241    if (mCert) {
242      PRBool otherHasCert;
243      aOther->GetHasCertificate(&otherHasCert);
244      if (!otherHasCert) {
245        return NS_OK;
246      }
247
248      nsXPIDLCString otherCertID;
249      aOther->GetCertificateID(getter_Copies(otherCertID));
250      *aResult = otherCertID.Equals(mCert->certificateID);
251      return NS_OK;
252    }
253
254    // Codebases are equal if they have the same origin.
255    nsIURI *origin = mDomain ? mDomain : mCodebase;
256    nsCOMPtr<nsIURI> otherOrigin;
257    aOther->GetDomain(getter_AddRefs(otherOrigin));
258    if (!otherOrigin) {
259      aOther->GetURI(getter_AddRefs(otherOrigin));
260    }
261
262    return nsScriptSecurityManager::GetScriptSecurityManager()
263           ->SecurityCompareURIs(origin, otherOrigin, aResult);
264  }
265
266  *aResult = PR_TRUE;
267  return NS_OK;
268}
269
270NS_IMETHODIMP
271nsPrincipal::Subsumes(nsIPrincipal *aOther, PRBool *aResult)
272{
273  return Equals(aOther, aResult);
274}
275
276NS_IMETHODIMP
277nsPrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
278{
279  // If this principal is marked invalid, can't enable any capabilities
280  nsCStringKey invalidKey(sInvalid);
281  if (mCapabilities.Exists(&invalidKey)) {
282    *result = nsIPrincipal::ENABLE_DENIED;
283
284    return NS_OK;
285  }
286
287  if (!mCert && !mTrusted) {
288    NS_ASSERTION(mInitialized, "Trying to enable a capability on an "
289                               "uninitialized principal");
290
291    // If we are a non-trusted codebase principal, capabilities can not
292    // be enabled if the user has not set the pref allowing scripts to
293    // request enhanced capabilities; however, the file: and resource:
294    // schemes are special and may be able to get extra capabilities
295    // even with the pref disabled.
296
297    static const char pref[] = "signed.applets.codebase_principal_support";
298    nsCOMPtr<nsIPrefBranch> prefBranch =
299      do_GetService(NS_PREFSERVICE_CONTRACTID);
300    if (prefBranch) {
301      PRBool mightEnable;
302      nsresult rv = prefBranch->GetBoolPref(pref, &mightEnable);
303      if (NS_FAILED(rv) || !mightEnable) {
304        rv = mCodebase->SchemeIs("file", &mightEnable);
305        if (NS_FAILED(rv) || !mightEnable) {
306          rv = mCodebase->SchemeIs("resource", &mightEnable);
307          if (NS_FAILED(rv) || !mightEnable) {
308            *result = nsIPrincipal::ENABLE_DENIED;
309
310            return NS_OK;
311          }
312        }
313      }
314    }
315  }
316
317  const char *start = capability;
318  *result = nsIPrincipal::ENABLE_GRANTED;
319  for(;;) {
320    const char *space = PL_strchr(start, ' ');
321    PRInt32 len = space ? space - start : strlen(start);
322    nsCAutoString capString(start, len);
323    nsCStringKey key(capString);
324    PRInt16 value = (PRInt16)NS_PTR_TO_INT32(mCapabilities.Get(&key));
325    if (value == 0 || value == nsIPrincipal::ENABLE_UNKNOWN) {
326      // We don't know whether we can enable this capability,
327      // so we should ask the user.
328      value = nsIPrincipal::ENABLE_WITH_USER_PERMISSION;
329    }
330
331    if (value < *result) {
332      *result = value;
333    }
334
335    if (!space) {
336      break;
337    }
338
339    start = space + 1;
340  }
341
342  return NS_OK;
343}
344
345NS_IMETHODIMP
346nsPrincipal::SetCanEnableCapability(const char *capability,
347                                    PRInt16 canEnable)
348{
349  // If this principal is marked invalid, can't enable any capabilities
350
351  nsCStringKey invalidKey(sInvalid);
352  if (mCapabilities.Exists(&invalidKey)) {
353    return NS_OK;
354  }
355
356  if (PL_strcmp(capability, sInvalid) == 0) {
357    mCapabilities.Reset();
358  }
359
360  const char *start = capability;
361  for(;;) {
362    const char *space = PL_strchr(start, ' ');
363    int len = space ? space - start : strlen(start);
364    nsCAutoString capString(start, len);
365    nsCStringKey key(capString);
366    mCapabilities.Put(&key, NS_INT32_TO_PTR(canEnable));
367    if (!space) {
368      break;
369    }
370
371    start = space + 1;
372  }
373
374  return NS_OK;
375}
376
377NS_IMETHODIMP
378nsPrincipal::IsCapabilityEnabled(const char *capability, void *annotation,
379                                 PRBool *result)
380{
381  *result = PR_FALSE;
382  nsHashtable *ht = (nsHashtable *) annotation;
383  if (!ht) {
384    return NS_OK;
385  }
386  const char *start = capability;
387  for(;;) {
388    const char *space = PL_strchr(start, ' ');
389    int len = space ? space - start : strlen(start);
390    nsCAutoString capString(start, len);
391    nsCStringKey key(capString);
392    *result = (ht->Get(&key) == (void *) AnnotationEnabled);
393    if (!*result) {
394      // If any single capability is not enabled, then return false.
395      return NS_OK;
396    }
397
398    if (!space) {
399      return NS_OK;
400    }
401
402    start = space + 1;
403  }
404
405  return NS_OK;
406}
407
408NS_IMETHODIMP
409nsPrincipal::EnableCapability(const char *capability, void **annotation)
410{
411  return SetCapability(capability, annotation, AnnotationEnabled);
412}
413
414NS_IMETHODIMP
415nsPrincipal::DisableCapability(const char *capability, void **annotation)
416{
417  return SetCapability(capability, annotation, AnnotationDisabled);
418}
419
420NS_IMETHODIMP
421nsPrincipal::RevertCapability(const char *capability, void **annotation)
422{
423  if (*annotation) {
424    nsHashtable *ht = (nsHashtable *) *annotation;
425    const char *start = capability;
426    for(;;) {
427      const char *space = PL_strchr(start, ' ');
428      int len = space ? space - start : strlen(start);
429      nsCAutoString capString(start, len);
430      nsCStringKey key(capString);
431      ht->Remove(&key);
432      if (!space) {
433        return NS_OK;
434      }
435
436      start = space + 1;
437    }
438  }
439  return NS_OK;
440}
441
442nsresult
443nsPrincipal::SetCapability(const char *capability, void **annotation,
444                           AnnotationValue value)
445{
446  if (*annotation == nsnull) {
447    *annotation = new nsHashtable(5);
448    if (!*annotation) {
449       return NS_ERROR_OUT_OF_MEMORY;
450     }
451
452    // This object owns its annotations. Save them so we can release
453    // them when we destroy this object.
454    mAnnotations.AppendElement(*annotation);
455  }
456
457  const char *start = capability;
458  for(;;) {
459    const char *space = PL_strchr(start, ' ');
460    int len = space ? space - start : strlen(start);
461    nsCAutoString capString(start, len);
462    nsCStringKey key(capString);
463    nsHashtable *ht = (nsHashtable *) *annotation;
464    ht->Put(&key, (void *) value);
465    if (!space) {
466      break;
467    }
468
469    start = space + 1;
470  }
471
472  return NS_OK;
473}
474
475NS_IMETHODIMP
476nsPrincipal::GetHasCertificate(PRBool* aResult)
477{
478  *aResult = (mCert != nsnull);
479
480  return NS_OK;
481}
482
483NS_IMETHODIMP
484nsPrincipal::GetURI(nsIURI** aURI)
485{
486  NS_IF_ADDREF(*aURI = mCodebase);
487
488  return NS_OK;
489}
490
491void
492nsPrincipal::SetURI(nsIURI* aURI)
493{
494  mCodebase = aURI;
495}
496
497
498nsresult
499nsPrincipal::SetCertificate(const char* aID, const char* aName)
500{
501  NS_ENSURE_STATE(!mCert);
502
503  if (!aID && !aName) {
504    return NS_ERROR_INVALID_POINTER;
505  }
506
507  mCert = new Certificate(aID, aName);
508  if (!mCert) {
509    return NS_ERROR_OUT_OF_MEMORY;
510  }
511
512  return NS_OK;
513}
514
515NS_IMETHODIMP
516nsPrincipal::GetCertificateID(char** aID)
517{
518  NS_ENSURE_STATE(mCert);
519
520  *aID = ToNewCString(mCert->certificateID);
521  if (!*aID) {
522    return NS_ERROR_OUT_OF_MEMORY;
523  }
524
525  return NS_OK;
526}
527
528NS_IMETHODIMP
529nsPrincipal::GetCommonName(char** aName)
530{
531  NS_ENSURE_STATE(mCert);
532
533  *aName = ToNewCString(mCert->commonName);
534  if (!*aName) {
535    return NS_ERROR_OUT_OF_MEMORY;
536  }
537
538  return NS_OK;
539}
540
541NS_IMETHODIMP
542nsPrincipal::SetCommonName(const char* aName)
543{
544  if (!mCert) {
545    NS_ERROR("You must first initialize the certificate with an ID");
546    return NS_ERROR_FAILURE;
547  }
548
549  mCert->commonName = aName;
550
551  return NS_OK;
552}
553
554
555NS_IMETHODIMP
556nsPrincipal::GetHashValue(PRUint32* aValue)
557{
558  NS_PRECONDITION(mCert || mCodebase, "Need a cert or codebase");
559
560  // If there is a certificate, it takes precendence over the codebase.
561  if (mCert) {
562    *aValue = nsCRT::HashCode(mCert->certificateID.get(), nsnull);
563  }
564  else {
565    nsCAutoString str;
566    mCodebase->GetSpec(str);
567    *aValue = nsCRT::HashCode(str.get(), nsnull);
568  }
569
570  return NS_OK;
571}
572
573NS_IMETHODIMP
574nsPrincipal::GetDomain(nsIURI** aDomain)
575{
576  NS_IF_ADDREF(*aDomain = mDomain);
577
578  return NS_OK;
579}
580
581NS_IMETHODIMP
582nsPrincipal::SetDomain(nsIURI* aDomain)
583{
584  mDomain = aDomain;
585  // Domain has changed, forget cached security policy
586  SetSecurityPolicy(nsnull);
587
588  return NS_OK;
589}
590
591nsresult
592nsPrincipal::InitFromPersistent(const char* aPrefName,
593                                const char* aToken,
594                                const char* aGrantedList,
595                                const char* aDeniedList,
596                                PRBool aIsCert,
597                                PRBool aTrusted)
598{
599  NS_PRECONDITION(mCapabilities.Count() == 0,
600                  "mCapabilities was already initialized?");
601  NS_PRECONDITION(mAnnotations.Count() == 0,
602                  "mAnnotations was already initialized?");
603  NS_PRECONDITION(!mInitialized, "We were already initialized?");
604
605  mInitialized = PR_TRUE;
606
607  nsresult rv;
608  if (aIsCert) {
609    rv = SetCertificate(aToken, nsnull);
610    if (NS_FAILED(rv)) {
611      return rv;
612    }
613  }
614  else {
615    rv = NS_NewURI(getter_AddRefs(mCodebase), aToken, nsnull);
616    if (NS_FAILED(rv)) {
617      NS_ERROR("Malformed URI in capability.principal preference.");
618      return rv;
619    }
620
621    mTrusted = aTrusted;
622  }
623
624  rv = mJSPrincipals.Init(this, aToken);
625  NS_ENSURE_SUCCESS(rv, rv);
626
627  //-- Save the preference name
628  mPrefName = aPrefName;
629
630  const char* ordinalBegin = PL_strpbrk(aPrefName, "1234567890");
631  if (ordinalBegin) {
632    PRIntn n = atoi(ordinalBegin);
633    if (sCapabilitiesOrdinal <= n) {
634      sCapabilitiesOrdinal = n + 1;
635    }
636  }
637
638  //-- Store the capabilities
639  rv = NS_OK;
640  if (aGrantedList) {
641    rv = SetCanEnableCapability(aGrantedList, nsIPrincipal::ENABLE_GRANTED);
642  }
643
644  if (NS_SUCCEEDED(rv) && aDeniedList) {
645    rv = SetCanEnableCapability(aDeniedList, nsIPrincipal::ENABLE_DENIED);
646  }
647
648  return rv;
649}
650
651struct CapabilityList
652{
653  nsCString* granted;
654  nsCString* denied;
655};
656
657PR_STATIC_CALLBACK(PRBool)
658AppendCapability(nsHashKey *aKey, void *aData, void *capListPtr)
659{
660  CapabilityList* capList = (CapabilityList*)capListPtr;
661  PRInt16 value = (PRInt16)NS_PTR_TO_INT32(aData);
662  nsCStringKey* key = (nsCStringKey *)aKey;
663  if (value == nsIPrincipal::ENABLE_GRANTED) {
664    capList->granted->Append(key->GetString(), key->GetStringLength());
665    capList->granted->Append(' ');
666  }
667  else if (value == nsIPrincipal::ENABLE_DENIED) {
668    capList->denied->Append(key->GetString(), key->GetStringLength());
669    capList->denied->Append(' ');
670  }
671
672  return PR_TRUE;
673}
674
675NS_IMETHODIMP
676nsPrincipal::GetPreferences(char** aPrefName, char** aID,
677                            char** aGrantedList, char** aDeniedList)
678{
679  if (mPrefName.IsEmpty()) {
680    if (mCert) {
681      mPrefName.Assign("capability.principal.certificate.p");
682    }
683    else {
684      mPrefName.Assign("capability.principal.codebase.p");
685    }
686
687    mPrefName.AppendInt(sCapabilitiesOrdinal++);
688    mPrefName.Append(".id");
689  }
690
691  *aPrefName = nsnull;
692  *aID = nsnull;
693  *aGrantedList = nsnull;
694  *aDeniedList = nsnull;
695
696  char *prefName = nsnull;
697  char *id = nsnull;
698  char *granted = nsnull;
699  char *denied = nsnull;
700
701  //-- Preference name
702  prefName = ToNewCString(mPrefName);
703  if (!prefName) {
704    return NS_ERROR_OUT_OF_MEMORY;
705  }
706
707  //-- ID
708  nsresult rv;
709  if (mCert) {
710    rv = GetCertificateID(&id);
711  }
712  else {
713    rv = GetOrigin(&id);
714  }
715
716  if (NS_FAILED(rv)) {
717    nsMemory::Free(prefName);
718    return rv;
719  }
720
721  //-- Capabilities
722  nsCAutoString grantedListStr, deniedListStr;
723  CapabilityList capList = CapabilityList();
724  capList.granted = &grantedListStr;
725  capList.denied = &deniedListStr;
726  mCapabilities.Enumerate(AppendCapability, (void*)&capList);
727
728  if (!grantedListStr.IsEmpty()) {
729    grantedListStr.Truncate(grantedListStr.Length() - 1);
730    granted = ToNewCString(grantedListStr);
731    if (!granted) {
732      nsMemory::Free(prefName);
733      nsMemory::Free(id);
734      return NS_ERROR_OUT_OF_MEMORY;
735    }
736  }
737
738  if (!deniedListStr.IsEmpty()) {
739    deniedListStr.Truncate(deniedListStr.Length() - 1);
740    denied = ToNewCString(deniedListStr);
741    if (!denied) {
742      nsMemory::Free(prefName);
743      nsMemory::Free(id);
744      if (granted) {
745        nsMemory::Free(granted);
746      }
747      return NS_ERROR_OUT_OF_MEMORY;
748    }
749  }
750
751  *aPrefName = prefName;
752  *aID = id;
753  *aGrantedList = granted;
754  *aDeniedList = denied;
755
756  return NS_OK;
757}
758
759PR_STATIC_CALLBACK(nsresult)
760ReadAnnotationEntry(nsIObjectInputStream* aStream, nsHashKey** aKey,
761                    void** aData)
762{
763  nsresult rv;
764  nsCStringKey* key = new nsCStringKey(aStream, &rv);
765  if (NS_FAILED(rv)) {
766    return rv;
767  }
768
769  PRUint32 value;
770  rv = aStream->Read32(&value);
771  if (NS_FAILED(rv)) {
772    delete key;
773    return rv;
774  }
775
776  *aKey = key;
777  *aData = (void*) value;
778  return NS_OK;
779}
780
781PR_STATIC_CALLBACK(void)
782FreeAnnotationEntry(nsIObjectInputStream* aStream, nsHashKey* aKey,
783                    void* aData)
784{
785  delete aKey;
786}
787
788NS_IMETHODIMP
789nsPrincipal::Read(nsIObjectInputStream* aStream)
790{
791  PRUint32 annotationCount;
792  nsresult rv = aStream->Read32(&annotationCount);
793  if (NS_FAILED(rv)) {
794    return rv;
795  }
796
797  for (PRInt32 i = 0, n = PRInt32(annotationCount); i < n; i++) {
798    nsHashtable *ht = new nsHashtable(aStream,
799                                      ReadAnnotationEntry,
800                                      FreeAnnotationEntry,
801                                      &rv);
802    if (!ht) {
803      return NS_ERROR_OUT_OF_MEMORY;
804    }
805
806    if (NS_FAILED(rv)) {
807      delete ht;
808      return rv;
809    }
810
811    if (!mAnnotations.InsertElementAt(NS_REINTERPRET_CAST(void*, ht), i)) {
812      delete ht;
813      return NS_ERROR_OUT_OF_MEMORY;
814    }
815  }
816
817  PRBool hasCapabilities;
818  rv = aStream->ReadBoolean(&hasCapabilities);
819  if (NS_SUCCEEDED(rv) && hasCapabilities) {
820    mCapabilities = nsHashtable(aStream,
821                                ReadAnnotationEntry,
822                                FreeAnnotationEntry,
823                                &rv);
824  }
825
826  if (NS_FAILED(rv)) {
827    return rv;
828  }
829
830  rv = NS_ReadOptionalCString(aStream, mPrefName);
831  if (NS_FAILED(rv)) {
832    return rv;
833  }
834
835  return NS_OK;
836}
837
838PR_STATIC_CALLBACK(nsresult)
839WriteScalarValue(nsIObjectOutputStream* aStream, void* aData)
840{
841  PRUint32 value = NS_PTR_TO_INT32(aData);
842
843  return aStream->Write32(value);
844}
845
846NS_IMETHODIMP
847nsPrincipal::Write(nsIObjectOutputStream* aStream)
848{
849  PRUint32 annotationCount = PRUint32(mAnnotations.Count());
850  nsresult rv = aStream->Write32(annotationCount);
851  if (NS_FAILED(rv)) {
852    return rv;
853  }
854
855  for (PRInt32 i = 0, n = PRInt32(annotationCount); i < n; i++) {
856    nsHashtable *ht = NS_REINTERPRET_CAST(nsHashtable *, mAnnotations[i]);
857    rv = ht->Write(aStream, WriteScalarValue);
858    if (NS_FAILED(rv)) {
859      return rv;
860    }
861  }
862
863  PRBool hasCapabilities = (mCapabilities.Count() > 0);
864  rv = aStream->WriteBoolean(hasCapabilities);
865  if (NS_SUCCEEDED(rv) && hasCapabilities) {
866    rv = mCapabilities.Write(aStream, WriteScalarValue);
867  }
868
869  if (NS_FAILED(rv)) {
870    return rv;
871  }
872
873  rv = NS_WriteOptionalStringZ(aStream, mPrefName.get());
874  if (NS_FAILED(rv)) {
875    return rv;
876  }
877
878  return NS_OK;
879}
880
881// nsIPrincipalObsolete interface
882
883NS_IMETHODIMP
884nsPrincipal::ToString(char **aResult)
885{
886  if (mCert)
887    return nsPrincipal::GetCertificateID(aResult);
888
889  return nsPrincipal::GetOrigin(aResult);
890}
891
892NS_IMETHODIMP
893nsPrincipal::ToUserVisibleString(char **aResult)
894{
895  if (mCert)
896    return nsPrincipal::GetCommonName(aResult);
897
898  return nsPrincipal::GetOrigin(aResult);
899}
900
901NS_IMETHODIMP
902nsPrincipal::Equals(nsIPrincipalObsolete *aOther, PRBool *aResult)
903{
904  nsCOMPtr<nsIPrincipal> princ = do_QueryInterface(aOther);
905  return nsPrincipal::Equals(princ, aResult);
906}
907
908NS_IMETHODIMP
909nsPrincipal::HashValue(PRUint32 *aResult)
910{
911  return nsPrincipal::GetHashValue(aResult);
912}
913
914NS_IMETHODIMP
915nsPrincipal::GetJSPrincipals(JSPrincipals **aResult)
916{
917  *aResult = &mJSPrincipals;
918  JSPRINCIPALS_HOLD(nsnull, *aResult);
919  return NS_OK;
920}
Note: See TracBrowser for help on using the repository browser.