Back to index

lightning-sunbird  0.9+nobinonly
nsAddbookProtocolHandler.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.org 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  *   Seth Spitzer <sspitzer@netscape.com>
00024  *   Pierre Phaneuf <pp@ludusdesign.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 #include "msgCore.h"    // precompiled header...
00040 #include "nsXPIDLString.h"
00041 #include "nsReadableUtils.h"
00042 #include "nsIIOService.h"
00043 
00044 #include "nsIStreamListener.h"
00045 #include "nsAddbookProtocolHandler.h"
00046 
00047 #include "nsAddbookUrl.h"
00048 #include "nsAddbookProtocolHandler.h"
00049 #include "nsIFileSpec.h"
00050 #include "nsCOMPtr.h"
00051 #include "nsAbBaseCID.h"
00052 #include "nsNetUtil.h"
00053 #include "nsIStringStream.h"
00054 #include "nsIAddrBookSession.h"
00055 #include "nsIAbMDBCard.h"
00056 #include "nsIAbDirectory.h"
00057 #include "nsIRDFResource.h"
00058 #include "nsIRDFService.h"
00059 #include "nsRDFCID.h"
00060 #include "prmem.h"
00061 
00062 #include "nsIStringBundle.h"
00063 #include "nsIServiceManager.h"
00064 
00065 nsAddbookProtocolHandler::nsAddbookProtocolHandler()
00066 {
00067   mAddbookOperation = nsIAddbookUrlOperation::InvalidUrl;
00068 }
00069 
00070 nsAddbookProtocolHandler::~nsAddbookProtocolHandler()
00071 {
00072 }
00073 
00074 NS_IMPL_ISUPPORTS1(nsAddbookProtocolHandler, nsIProtocolHandler)
00075 
00076 NS_IMETHODIMP nsAddbookProtocolHandler::GetScheme(nsACString &aScheme)
00077 {
00078        aScheme = "addbook";
00079        return NS_OK; 
00080 }
00081 
00082 NS_IMETHODIMP nsAddbookProtocolHandler::GetDefaultPort(PRInt32 *aDefaultPort)
00083 {
00084   return NS_OK;
00085 }
00086 
00087 NS_IMETHODIMP nsAddbookProtocolHandler::GetProtocolFlags(PRUint32 *aUritype)
00088 {
00089   *aUritype = URI_STD;
00090   return NS_OK;
00091 }
00092 
00093 NS_IMETHODIMP nsAddbookProtocolHandler::NewURI(const nsACString &aSpec,
00094                                                const char *aOriginCharset, // ignored
00095                                                nsIURI *aBaseURI,
00096                                                nsIURI **_retval)
00097 {
00098   nsresult rv;
00099        nsCOMPtr <nsIAddbookUrl> addbookUrl = do_CreateInstance(NS_ADDBOOKURL_CONTRACTID, &rv);
00100   NS_ENSURE_SUCCESS(rv,rv);
00101 
00102   rv = addbookUrl->SetSpec(aSpec);
00103   NS_ENSURE_SUCCESS(rv,rv);
00104 
00105   nsCOMPtr <nsIURI> uri = do_QueryInterface(addbookUrl, &rv);
00106   NS_ENSURE_SUCCESS(rv,rv);
00107 
00108   NS_ADDREF(*_retval = uri);
00109   return NS_OK;
00110 }
00111 
00112 NS_IMETHODIMP 
00113 nsAddbookProtocolHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval)
00114 {
00115     // don't override anything.  
00116     *_retval = PR_FALSE;
00117     return NS_OK;
00118 }
00119 
00120 nsresult
00121 nsAddbookProtocolHandler::GenerateXMLOutputChannel( nsString &aOutput,
00122                                                      nsIAddbookUrl *addbookUrl,
00123                                                      nsIURI *aURI, 
00124                                                      nsIChannel **_retval)
00125 {
00126   nsIChannel                *channel;
00127   nsCOMPtr<nsIInputStream>  inStr;
00128   NS_ConvertUCS2toUTF8 utf8String(aOutput.get());
00129 
00130   nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inStr), utf8String);
00131   NS_ENSURE_SUCCESS(rv, rv);
00132   
00133   rv = NS_NewInputStreamChannel(&channel, aURI, inStr,
00134                                 NS_LITERAL_CSTRING("text/xml"));
00135   NS_ENSURE_SUCCESS(rv, rv);
00136   
00137   *_retval = channel;
00138   return rv;
00139 }
00140 
00141 NS_IMETHODIMP 
00142 nsAddbookProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
00143 {
00144   nsresult rv;
00145   nsCOMPtr <nsIAddbookUrl> addbookUrl = do_QueryInterface(aURI, &rv);
00146   NS_ENSURE_SUCCESS(rv,rv);
00147   
00148   rv = addbookUrl->GetAddbookOperation(&mAddbookOperation);
00149   NS_ENSURE_SUCCESS(rv,rv);
00150 
00151   if (mAddbookOperation == nsIAddbookUrlOperation::InvalidUrl) {
00152     nsAutoString errorString;
00153     errorString.AssignLiteral("Unsupported format/operation requested for ");
00154     nsCAutoString spec;
00155     rv = aURI->GetSpec(spec);
00156     NS_ENSURE_SUCCESS(rv,rv);
00157 
00158     AppendUTF8toUTF16(spec, errorString);
00159     rv = GenerateXMLOutputChannel(errorString, addbookUrl, aURI, _retval);
00160     NS_ENSURE_SUCCESS(rv,rv);
00161     return NS_OK;
00162   }
00163  
00164   if (mAddbookOperation == nsIAddbookUrlOperation::AddVCard) {
00165       // create an empty pipe for use with the input stream channel.
00166       nsCOMPtr<nsIInputStream> pipeIn;
00167       nsCOMPtr<nsIOutputStream> pipeOut;
00168       rv = NS_NewPipe(getter_AddRefs(pipeIn),
00169           getter_AddRefs(pipeOut));
00170       if (NS_FAILED(rv)) 
00171           return rv;
00172       
00173       pipeOut->Close();
00174       
00175       return NS_NewInputStreamChannel(_retval, aURI, pipeIn,
00176           NS_LITERAL_CSTRING("application/x-addvcard"));
00177   }
00178 
00179   nsString output;
00180   rv = GeneratePrintOutput(addbookUrl, output);
00181   if (NS_FAILED(rv)) {
00182     output.AssignLiteral("failed to print. url=");
00183     nsCAutoString spec;
00184     rv = aURI->GetSpec(spec);
00185     NS_ENSURE_SUCCESS(rv,rv);
00186     AppendUTF8toUTF16(spec, output);
00187   }
00188  
00189   rv = GenerateXMLOutputChannel(output, addbookUrl, aURI, _retval);
00190   NS_ENSURE_SUCCESS(rv,rv);
00191   return NS_OK;
00192 }
00193 
00194 nsresult    
00195 nsAddbookProtocolHandler::GeneratePrintOutput(nsIAddbookUrl *addbookUrl, 
00196                                               nsString &aOutput)
00197 {
00198   NS_ENSURE_ARG_POINTER(addbookUrl);
00199 
00200   nsCAutoString uri;
00201   nsresult rv = addbookUrl->GetPath(uri);
00202   NS_ENSURE_SUCCESS(rv,rv);
00203 
00204   nsCOMPtr<nsIRDFService> rdfService = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
00205   NS_ENSURE_SUCCESS(rv,rv);
00206 
00207   /* turn
00208    "//moz-abmdbdirectory/abook.mab?action=print"
00209    into "moz-abmdbdirectory://abook.mab"
00210   */
00211 
00212   /* step 1:  
00213    turn "//moz-abmdbdirectory/abook.mab?action=print"
00214    into "moz-abmdbdirectory/abook.mab?action=print"
00215    */
00216   if (uri[0] != '/' && uri[1] != '/')
00217     return NS_ERROR_UNEXPECTED;
00218 
00219   uri.Cut(0,2);
00220 
00221   /* step 2:  
00222    turn "moz-abmdbdirectory/abook.mab?action=print"
00223    into "moz-abmdbdirectory/abook.mab"
00224    */
00225   PRInt32 pos = uri.Find("?action=print");
00226        if (pos == kNotFound)
00227     return NS_ERROR_UNEXPECTED;
00228 
00229   uri.Truncate(pos);
00230 
00231   /* step 2:  
00232    turn "moz-abmdbdirectory/abook.mab"
00233    into "moz-abmdbdirectory://abook.mab"
00234    */
00235   pos = uri.Find("/");
00236   if (pos == kNotFound)
00237     return NS_ERROR_UNEXPECTED;
00238 
00239   uri.Insert('/', pos);
00240   uri.Insert(':', pos);
00241 
00242   nsCOMPtr <nsIRDFResource> resource;
00243   rv = rdfService->GetResource(uri, getter_AddRefs(resource));
00244   NS_ENSURE_SUCCESS(rv,rv);
00245   
00246   nsCOMPtr <nsIAbDirectory> directory = do_QueryInterface(resource, &rv);
00247   NS_ENSURE_SUCCESS(rv,rv);
00248 
00249   rv = BuildDirectoryXML(directory, aOutput);
00250   NS_ENSURE_SUCCESS(rv,rv);
00251 
00252   return NS_OK;
00253 }
00254 
00255 nsresult
00256 nsAddbookProtocolHandler::BuildDirectoryXML(nsIAbDirectory *aDirectory, 
00257                                        nsString &aOutput)
00258 {
00259   NS_ENSURE_ARG_POINTER(aDirectory);
00260 
00261   nsresult rv;    
00262   nsCOMPtr<nsIEnumerator> cardsEnumerator;
00263   nsCOMPtr<nsIAbCard> card;
00264 
00265   aOutput.AppendLiteral("<?xml version=\"1.0\"?>\n"
00266                         "<?xml-stylesheet type=\"text/css\" href=\"chrome://messenger/content/addressbook/print.css\"?>\n"
00267                         "<directory>\n");
00268 
00269   // Get Address Book string and set it as title of XML document
00270   nsCOMPtr<nsIStringBundle> bundle;
00271   nsCOMPtr<nsIStringBundleService> stringBundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); 
00272   if (NS_SUCCEEDED(rv)) {
00273     rv = stringBundleService->CreateBundle("chrome://messenger/locale/addressbook/addressBook.properties", getter_AddRefs(bundle));
00274     if (NS_SUCCEEDED(rv)) {
00275       nsXPIDLString addrBook;
00276       rv = bundle->GetStringFromName(NS_LITERAL_STRING("addressBook").get(), getter_Copies(addrBook));
00277       if (NS_SUCCEEDED(rv)) {
00278         aOutput.AppendLiteral("<title xmlns=\"http://www.w3.org/1999/xhtml\">");
00279         aOutput.Append(addrBook);
00280         aOutput.AppendLiteral("</title>\n");
00281       }
00282     }
00283   }
00284 
00285  
00286   rv = aDirectory->GetChildCards(getter_AddRefs(cardsEnumerator));
00287   if (NS_SUCCEEDED(rv) && cardsEnumerator)
00288   {
00289     nsCOMPtr<nsISupports> item;
00290     for (rv = cardsEnumerator->First(); NS_SUCCEEDED(rv); rv = cardsEnumerator->Next())
00291     {
00292       rv = cardsEnumerator->CurrentItem(getter_AddRefs(item));
00293       if (NS_SUCCEEDED(rv))
00294       {
00295         nsCOMPtr <nsIAbCard> card = do_QueryInterface(item);
00296         nsXPIDLString xmlSubstr;
00297 
00298         rv = card->ConvertToXMLPrintData(getter_Copies(xmlSubstr));
00299         NS_ENSURE_SUCCESS(rv,rv);
00300 
00301         aOutput.AppendLiteral("<separator/>");
00302         aOutput.Append(xmlSubstr);
00303       }
00304     }
00305     aOutput.AppendLiteral("<separator/>");
00306   }
00307 
00308   aOutput.AppendLiteral("</directory>\n");
00309 
00310   return NS_OK;
00311 }