Back to index

lightning-sunbird  0.9+nobinonly
Classes | Public Types | Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Static Protected Attributes
nsDirIndexParser Class Reference

#include <nsDirIndexParser.h>

Inheritance diagram for nsDirIndexParser:
Inheritance graph
[legend]
Collaboration diagram for nsDirIndexParser:
Collaboration graph
[legend]

List of all members.

Classes

struct  Field

Public Types

enum  fieldType {
  FIELD_UNKNOWN = 0, FIELD_FILENAME, FIELD_DESCRIPTION, FIELD_CONTENTLENGTH,
  FIELD_LASTMODIFIED, FIELD_CONTENTTYPE, FIELD_FILETYPE
}

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSIDIRINDEXPARSER 
nsDirIndexParser ()
virtual ~nsDirIndexParser ()
nsresult Init ()
void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, in nsIInputStream aInputStream, in unsigned long aOffset, in unsigned long aCount)
 Called when the next chunk of data (corresponding to the request) may be read without blocking the calling thread.
void onStartRequest (in nsIRequest aRequest, in nsISupports aContext)
 Called to signify the beginning of an asynchronous request.
void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, in nsresult aStatusCode)
 Called to signify the end of an asynchronous request.

Public Attributes

attribute nsIDirIndexListener listener
 The interface to use as a callback for new entries.
readonly attribute string comment
 The comment given, if any This result is only valid after OnStopRequest has occurred, because it can occur anywhere in the datastream.
attribute string encoding
 The encoding to use.

Protected Member Functions

nsresult ProcessData (nsIRequest *aRequest, nsISupports *aCtxt)
nsresult ParseFormat (const char *buf)
nsresult ParseData (nsIDirIndex *aIdx, char *aDataStr)

Protected Attributes

nsCOMPtr< nsIDirIndexListenermListener
nsCString mEncoding
nsCString mComment
nsCString mBuf
PRInt32 mLineStart
PRBool mHasDescription
intmFormat

Static Protected Attributes

static Field gFieldTable []
static nsrefcnt gRefCntParser = 0
static nsITextToSubURIgTextToSubURI

Detailed Description

Definition at line 53 of file nsDirIndexParser.h.


Class Documentation

struct nsDirIndexParser::Field

Definition at line 88 of file nsDirIndexParser.h.

Class Members
const char * mName
fieldType mType

Member Enumeration Documentation

Enumerator:
FIELD_UNKNOWN 
FIELD_FILENAME 
FIELD_DESCRIPTION 
FIELD_CONTENTLENGTH 
FIELD_LASTMODIFIED 
FIELD_CONTENTTYPE 
FIELD_FILETYPE 

Definition at line 64 of file nsDirIndexParser.h.


Constructor & Destructor Documentation

NS_DECL_ISUPPORTS NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSIDIRINDEXPARSER nsDirIndexParser::nsDirIndexParser ( )

Definition at line 101 of file nsDirIndexParser.cpp.

                                    {
  delete[] mFormat;
  // XXX not threadsafe
  if (--gRefCntParser == 0) {
    NS_IF_RELEASE(gTextToSubURI);
  }
}

Member Function Documentation

Definition at line 68 of file nsDirIndexParser.cpp.

                       {
  mLineStart = 0;
  mHasDescription = PR_FALSE;
  mFormat = nsnull;

  // get default charset to be used for directory listings (fallback to
  // ISO-8859-1 if pref is unavailable).
  NS_NAMED_LITERAL_CSTRING(kFallbackEncoding, "ISO-8859-1");
  nsXPIDLString defCharset;
  nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
  if (prefs) {
    nsCOMPtr<nsIPrefLocalizedString> prefVal;
    prefs->GetComplexValue("intl.charset.default",
                           NS_GET_IID(nsIPrefLocalizedString),
                           getter_AddRefs(prefVal));
    if (prefVal)
      prefVal->ToString(getter_Copies(defCharset));
  }
  if (!defCharset.IsEmpty())
    LossyCopyUTF16toASCII(defCharset, mEncoding); // charset labels are always ASCII
  else
    mEncoding.Assign(kFallbackEncoding);
 
  nsresult rv;
  // XXX not threadsafe
  if (gRefCntParser++ == 0)
    rv = CallGetService(NS_ITEXTTOSUBURI_CONTRACTID, &gTextToSubURI);
  else
    rv = NS_OK;

  return rv;
}

Here is the call graph for this function:

void nsIStreamListener::onDataAvailable ( in nsIRequest  aRequest,
in nsISupports  aContext,
in nsIInputStream  aInputStream,
in unsigned long  aOffset,
in unsigned long  aCount 
) [inherited]

Called when the next chunk of data (corresponding to the request) may be read without blocking the calling thread.

The onDataAvailable impl must read exactly |aCount| bytes of data before returning.

Parameters:
aRequestrequest corresponding to the source of the data
aContextuser defined context
aInputStreaminput stream containing the data chunk
aOffsetNumber of bytes that were sent in previous onDataAvailable calls for this request. In other words, the sum of all previous count parameters. If that number is greater than or equal to 2^32, this parameter will be PR_UINT32_MAX (2^32 - 1).
aCountnumber of bytes available in the stream

NOTE: The aInputStream parameter must implement readSegments.

An exception thrown from onDataAvailable has the side-effect of causing the request to be canceled.

void nsIRequestObserver::onStartRequest ( in nsIRequest  aRequest,
in nsISupports  aContext 
) [inherited]

Called to signify the beginning of an asynchronous request.

Parameters:
aRequestrequest being observed
aContextuser defined context

An exception thrown from onStartRequest has the side-effect of causing the request to be canceled.

Here is the caller graph for this function:

void nsIRequestObserver::onStopRequest ( in nsIRequest  aRequest,
in nsISupports  aContext,
in nsresult  aStatusCode 
) [inherited]

Called to signify the end of an asynchronous request.

This call is always preceded by a call to onStartRequest.

Parameters:
aRequestrequest being observed
aContextuser defined context
aStatusCodereason for stopping (NS_OK if completed successfully)

An exception thrown from onStopRequest is generally ignored.

Here is the caller graph for this function:

nsresult nsDirIndexParser::ParseData ( nsIDirIndex aIdx,
char *  aDataStr 
) [protected]

Definition at line 242 of file nsDirIndexParser.cpp.

                                                             {
  // Parse a "201" data line, using the field ordering specified in
  // mFormat.

  if (!mFormat) {
    // Ignore if we haven't seen a format yet.
    return NS_OK;
  }

  nsresult rv = NS_OK;

  nsCAutoString filename;

  for (PRInt32 i = 0; mFormat[i] != -1; ++i) {
    // If we've exhausted the data before we run out of fields, just
    // bail.
    if (! *aDataStr)
      break;

    while (*aDataStr && nsCRT::IsAsciiSpace(*aDataStr))
      ++aDataStr;

    char    *value = aDataStr;

    if (*aDataStr == '"' || *aDataStr == '\'') {
      // it's a quoted string. snarf everything up to the next quote character
      const char quotechar = *(aDataStr++);
      ++value;
      while (*aDataStr && *aDataStr != quotechar)
        ++aDataStr;
      *aDataStr++ = '\0';

      if (! aDataStr) {
        NS_WARNING("quoted value not terminated");
      }
    } else {
      // it's unquoted. snarf until we see whitespace.
      value = aDataStr;
      while (*aDataStr && (!nsCRT::IsAsciiSpace(*aDataStr)))
        ++aDataStr;
      *aDataStr++ = '\0';
    }

    fieldType t = fieldType(mFormat[i]);
    switch (t) {
    case FIELD_FILENAME: {
      // don't unescape at this point, so that UnEscapeAndConvert() can
      filename = value;
      
      PRBool  success = PR_FALSE;
      
      nsAutoString entryuri;
      
      if (gTextToSubURI) {
        PRUnichar   *result = nsnull;
        if (NS_SUCCEEDED(rv = gTextToSubURI->UnEscapeAndConvert(mEncoding.get(), filename.get(),
                                                                &result)) && (result)) {
          if (*result) {
            aIdx->SetLocation(filename.get());
            if (!mHasDescription)
              aIdx->SetDescription(result);
            success = PR_TRUE;
          }
          Recycle(result);
        } else {
          NS_WARNING("UnEscapeAndConvert error");
        }
      }
      
      if (success == PR_FALSE) {
        // if unsuccessfully at charset conversion, then
        // just fallback to unescape'ing in-place
        // XXX - this shouldn't be using UTF8, should it?
        // when can we fail to get the service, anyway? - bbaetz
        aIdx->SetLocation(filename.get());
        if (!mHasDescription) {
          aIdx->SetDescription(NS_ConvertUTF8toUCS2(value).get());
        }
      }
    }
      break;
    case FIELD_DESCRIPTION:
      nsUnescape(value);
      aIdx->SetDescription(NS_ConvertUTF8toUCS2(value).get());
      break;
    case FIELD_CONTENTLENGTH:
      {
        PRInt64 len;
        PRInt32 status = PR_sscanf(value, "%lld", &len);
        if (status == 1)
          aIdx->SetSize(len);
        else
          aIdx->SetSize(LL_MAXUINT); // LL_MAXUINT means unknown
      }
      break;
    case FIELD_LASTMODIFIED:
      {
        PRTime tm;
        nsUnescape(value);
        if (PR_ParseTimeString(value, PR_FALSE, &tm) == PR_SUCCESS) {
          aIdx->SetLastModified(tm);
        }
      }
      break;
    case FIELD_CONTENTTYPE:
      aIdx->SetContentType(value);
      break;
    case FIELD_FILETYPE:
      // unescape in-place
      nsUnescape(value);
      if (!nsCRT::strcasecmp(value, "directory")) {
        aIdx->SetType(nsIDirIndex::TYPE_DIRECTORY);
      } else if (!nsCRT::strcasecmp(value, "file")) {
        aIdx->SetType(nsIDirIndex::TYPE_FILE);
      } else if (!nsCRT::strcasecmp(value, "symbolic-link")) {
        aIdx->SetType(nsIDirIndex::TYPE_SYMLINK);
      } else {
        aIdx->SetType(nsIDirIndex::TYPE_UNKNOWN);
      }
      break;
    case FIELD_UNKNOWN:
      // ignore
      break;
    }
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsDirIndexParser::ParseFormat ( const char *  buf) [protected]

Definition at line 178 of file nsDirIndexParser.cpp.

                                                    {
  // Parse a "200" format line, and remember the fields and their
  // ordering in mFormat. Multiple 200 lines stomp on each other.

  delete[] mFormat;

  // Lets find out how many elements we have.
  // easier to do this then realloc
  const char* pos = aFormatStr;
  int num = 0;
  do {
    while (*pos && nsCRT::IsAsciiSpace(PRUnichar(*pos)))
      ++pos;
    
    ++num;

    if (! *pos)
      break;

    while (*pos && !nsCRT::IsAsciiSpace(PRUnichar(*pos)))
      ++pos;

  } while (*pos);

  mFormat = new int[num+1];
  mFormat[num] = -1;
  
  int formatNum=0;
  do {
    while (*aFormatStr && nsCRT::IsAsciiSpace(PRUnichar(*aFormatStr)))
      ++aFormatStr;
    
    if (! *aFormatStr)
      break;

    nsCAutoString name;
    PRInt32     len = 0;
    while (aFormatStr[len] && !nsCRT::IsAsciiSpace(PRUnichar(aFormatStr[len])))
      ++len;
    name.SetCapacity(len + 1);
    name.Append(aFormatStr, len);
    aFormatStr += len;
    
    // Okay, we're gonna monkey with the nsStr. Bold!
    name.SetLength(nsUnescapeCount(name.BeginWriting()));

    // All tokens are case-insensitive - http://www.mozilla.org/projects/netlib/dirindexformat.html
    if (name.LowerCaseEqualsLiteral("description"))
      mHasDescription = PR_TRUE;
    
    for (Field* i = gFieldTable; i->mName; ++i) {
      if (name.EqualsIgnoreCase(i->mName)) {
        mFormat[formatNum] = i->mType;
        ++formatNum;
        break;
      }
    }

  } while (*aFormatStr);
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsDirIndexParser::ProcessData ( nsIRequest aRequest,
nsISupports *  aCtxt 
) [protected]

Definition at line 401 of file nsDirIndexParser.cpp.

                                                                      {
  if (!mListener)
    return NS_ERROR_FAILURE;
  
  PRInt32     numItems = 0;
  
  while(PR_TRUE) {
    ++numItems;
    
    PRInt32             eol = mBuf.FindCharInSet("\n\r", mLineStart);
    if (eol < 0)        break;
    mBuf.SetCharAt(PRUnichar('\0'), eol);
    
    const char  *line = mBuf.get() + mLineStart;
    
    PRInt32 lineLen = eol - mLineStart;
    mLineStart = eol + 1;
    
    if (lineLen >= 4) {
      nsresult  rv;
      const char        *buf = line;
      
      if (buf[0] == '1') {
        if (buf[1] == '0') {
          if (buf[2] == '0' && buf[3] == ':') {
            // 100. Human-readable comment line. Ignore
          } else if (buf[2] == '1' && buf[3] == ':') {
            // 101. Human-readable information line.
            mComment.Append(buf + 4);

            char    *value = ((char *)buf) + 4;
            nsUnescape(value);
            mListener->OnInformationAvailable(aRequest, aCtxt, NS_ConvertUTF8toUTF16(value));

          } else if (buf[2] == '2' && buf[3] == ':') {
            // 102. Human-readable information line, HTML.
            mComment.Append(buf + 4);
          }
        }
      } else if (buf[0] == '2') {
        if (buf[1] == '0') {
          if (buf[2] == '0' && buf[3] == ':') {
            // 200. Define field names
            rv = ParseFormat(buf + 4);
            if (NS_FAILED(rv)) {
              return rv;
            }
          } else if (buf[2] == '1' && buf[3] == ':') {
            // 201. Field data
            nsCOMPtr<nsIDirIndex> idx = do_CreateInstance("@mozilla.org/dirIndex;1",&rv);
            if (NS_FAILED(rv))
              return rv;
            
            rv = ParseData(idx, ((char *)buf) + 4);
            if (NS_FAILED(rv)) {
              return rv;
            }

            mListener->OnIndexAvailable(aRequest, aCtxt, idx);
          }
        }
      } else if (buf[0] == '3') {
        if (buf[1] == '0') {
          if (buf[2] == '0' && buf[3] == ':') {
            // 300. Self-referring URL
          } else if (buf[2] == '1' && buf[3] == ':') {
            // 301. OUR EXTENSION - encoding
            int i = 4;
            while (buf[i] && nsCRT::IsAsciiSpace(buf[i]))
              ++i;
            
            if (buf[i])
              SetEncoding(buf+i);
          }
        }
      }
    }
  }
  
  return NS_OK;
}

Here is the call graph for this function:


Member Data Documentation

The comment given, if any This result is only valid after OnStopRequest has occurred, because it can occur anywhere in the datastream.

Definition at line 93 of file nsIDirIndexListener.idl.

The encoding to use.

Definition at line 98 of file nsIDirIndexListener.idl.

Initial value:
 {
  { "Filename", FIELD_FILENAME },
  { "Description", FIELD_DESCRIPTION },
  { "Content-Length", FIELD_CONTENTLENGTH },
  { "Last-Modified", FIELD_LASTMODIFIED },
  { "Content-Type", FIELD_CONTENTTYPE },
  { "File-Type", FIELD_FILETYPE },
  { nsnull, FIELD_UNKNOWN }
}

Definition at line 93 of file nsDirIndexParser.h.

nsrefcnt nsDirIndexParser::gRefCntParser = 0 [static, protected]

Definition at line 95 of file nsDirIndexParser.h.

Definition at line 96 of file nsDirIndexParser.h.

The interface to use as a callback for new entries.

Definition at line 86 of file nsIDirIndexListener.idl.

Definition at line 79 of file nsDirIndexParser.h.

Definition at line 78 of file nsDirIndexParser.h.

Definition at line 77 of file nsDirIndexParser.h.

Definition at line 82 of file nsDirIndexParser.h.

Definition at line 81 of file nsDirIndexParser.h.

Definition at line 80 of file nsDirIndexParser.h.

Definition at line 75 of file nsDirIndexParser.h.


The documentation for this class was generated from the following files: