Back to index

lightning-sunbird  0.9+nobinonly
rdfutil.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039 
00040   Implementations for a bunch of useful RDF utility routines.  Many of
00041   these will eventually be exported outside of RDF.DLL via the
00042   nsIRDFService interface.
00043 
00044   TO DO
00045 
00046   1) Make this so that it doesn't permanently leak the RDF service
00047      object.
00048 
00049   2) Make container functions thread-safe. They currently don't ensure
00050      that the RDF:nextVal property is maintained safely.
00051 
00052  */
00053 
00054 #include "nsCOMPtr.h"
00055 #include "nsIRDFDataSource.h"
00056 #include "nsIRDFNode.h"
00057 #include "nsIRDFService.h"
00058 #include "nsIServiceManager.h"
00059 #include "nsIURL.h"
00060 #include "nsIIOService.h"
00061 #include "nsIURL.h"
00062 #include "nsNetUtil.h"
00063 #include "nsRDFCID.h"
00064 #include "nsString.h"
00065 #include "nsXPIDLString.h"
00066 #include "nsUnicharUtils.h"
00067 #include "prtime.h"
00068 #include "rdfutil.h"
00069 
00071 
00072 nsresult
00073 rdf_MakeRelativeRef(const nsCSubstring& aBaseURI, nsCString& aURI)
00074 {
00075     // This implementation is extremely simple: e.g., it can't compute
00076     // relative paths, or anything fancy like that. If the context URI
00077     // is not a prefix of the URI in question, we'll just bail.
00078     PRUint32 prefixLen = aBaseURI.Length();
00079     if (prefixLen != 0 && StringBeginsWith(aURI, aBaseURI)) {
00080         if (prefixLen < aURI.Length() && aURI.CharAt(prefixLen) == '/')
00081             ++prefixLen; // chop the leading slash so it's not `absolute'
00082 
00083         aURI.Cut(0, prefixLen);
00084     }
00085 
00086     return NS_OK;
00087 }
00088 
00089 static PRBool
00090 rdf_RequiresAbsoluteURI(const nsString& uri)
00091 {
00092     // cheap shot at figuring out if this requires an absolute url translation
00093     return !(StringBeginsWith(uri, NS_LITERAL_STRING("urn:")) ||
00094              StringBeginsWith(uri, NS_LITERAL_STRING("chrome:")) ||
00095              StringBeginsWith(uri, NS_LITERAL_STRING("nc:"),
00096                               nsCaseInsensitiveStringComparator()));
00097 }
00098 
00099 nsresult
00100 rdf_MakeAbsoluteURI(const nsString& aBaseURI, nsString& aURI)
00101 {
00102     nsresult rv;
00103     nsAutoString result;
00104 
00105     if (!rdf_RequiresAbsoluteURI(aURI))
00106         return NS_OK;
00107     
00108     nsCOMPtr<nsIURI> base;
00109     rv = NS_NewURI(getter_AddRefs(base), aBaseURI);
00110     if (NS_FAILED(rv)) return rv;
00111 
00112     rv = NS_MakeAbsoluteURI(result, aURI, base);
00113 
00114     if (NS_SUCCEEDED(rv)) {
00115         aURI = result;
00116     }
00117     else {
00118         // There are some ugly URIs (e.g., "NC:Foo") that netlib can't
00119         // parse. If NS_MakeAbsoluteURL fails, then just punt and
00120         // assume that aURI was already absolute.
00121     }
00122 
00123     return NS_OK;
00124 }
00125 
00126 
00127 nsresult
00128 rdf_MakeAbsoluteURI(nsIURI* aBase, nsString& aURI)
00129 {
00130     nsresult rv;
00131 
00132     if (!rdf_RequiresAbsoluteURI(aURI))
00133         return NS_OK;
00134 
00135     nsAutoString result;
00136 
00137     rv = NS_MakeAbsoluteURI(result, aURI, aBase);
00138 
00139     if (NS_SUCCEEDED(rv)) {
00140         aURI = result;
00141     }
00142     else {
00143         // There are some ugly URIs (e.g., "NC:Foo") that netlib can't
00144         // parse. If NS_MakeAbsoluteURL fails, then just punt and
00145         // assume that aURI was already absolute.
00146     }
00147 
00148     return NS_OK;
00149 }
00150 
00151 nsresult
00152 rdf_MakeAbsoluteURI(nsIURI* aBase, nsCString& aURI)
00153 {
00154     nsresult rv;
00155     nsXPIDLCString result;
00156 
00157     rv = NS_MakeAbsoluteURI(getter_Copies(result), aURI.get(), aBase);
00158 
00159     if (NS_SUCCEEDED(rv)) {
00160         aURI.Assign(result);
00161     }
00162     else {
00163         // There are some ugly URIs (e.g., "NC:Foo") that netlib can't
00164         // parse. If NS_MakeAbsoluteURL fails, then just punt and
00165         // assume that aURI was already absolute.
00166     }
00167 
00168     return NS_OK;
00169 }
00170 
00171 void
00172 rdf_FormatDate(PRTime aTime, nsACString &aResult)
00173 {
00174     // Outputs Unixish date in GMT plus usecs; e.g.,
00175     //   Wed Jan  9 19:15:13 GMT 2002 +002441
00176     //
00177     PRExplodedTime t;
00178     PR_ExplodeTime(aTime, PR_LocalTimeParameters, &t);
00179 
00180     char buf[256];
00181     PR_FormatTimeUSEnglish(buf, sizeof buf, "%a %b %d %H:%M:%S %Z %Y", &t);
00182     aResult.Append(buf);
00183 
00184     // usecs
00185     aResult.Append(" +");
00186     PRInt32 usec = t.tm_usec;
00187     for (PRInt32 digit = 100000; digit > 1; digit /= 10) {
00188         aResult.Append(char('0' + (usec / digit)));
00189         usec %= digit;
00190     }
00191     aResult.Append(char('0' + usec));
00192 }
00193 
00194 PRTime
00195 rdf_ParseDate(const nsACString &aTime)
00196 {
00197     PRTime t;
00198     PR_ParseTimeString(PromiseFlatCString(aTime).get(), PR_TRUE, &t);
00199 
00200     PRInt32 usec = 0;
00201 
00202     nsACString::const_iterator begin, digit, end;
00203     aTime.BeginReading(begin);
00204     aTime.EndReading(end);
00205 
00206     // Walk backwards until we find a `+', run out of string, or a
00207     // non-numeric character.
00208     digit = end;
00209     while (--digit != begin && *digit != '+') {
00210         if (*digit < '0' || *digit > '9')
00211             break;
00212     }
00213 
00214     if (digit != begin && *digit == '+') {
00215         // There's a usec field specified (or, at least, something
00216         // that looks close enough. Parse it, and add it to the time.
00217         while (++digit != end) {
00218             usec *= 10;
00219             usec += *digit - '0';
00220         }
00221 
00222         PRTime temp;
00223         LL_I2L(temp, usec);
00224         LL_ADD(t, t, temp);
00225     }
00226 
00227     return t;
00228 }