Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Member Functions | Private Attributes
nsGnomeVFSInputStream Class Reference
Inheritance diagram for nsGnomeVFSInputStream:
Inheritance graph
[legend]
Collaboration diagram for nsGnomeVFSInputStream:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSIINPUTSTREAM 
nsGnomeVFSInputStream (const nsCString &uriSpec)
 ~nsGnomeVFSInputStream ()
void SetChannel (nsIChannel *channel)
void close ()
 Close the stream.
unsigned long available ()
unsigned long read (in charPtr aBuf, in unsigned long aCount)
 Read data from the stream.
unsigned long readSegments (in nsWriteSegmentFun aWriter, in voidPtr aClosure, in unsigned long aCount)
 Low-level read method that has access to the stream's underlying buffer.
boolean isNonBlocking ()

Private Member Functions

GnomeVFSResult DoOpen ()
GnomeVFSResult DoRead (char *aBuf, PRUint32 aCount, PRUint32 *aCountRead)
nsresult SetContentTypeOfChannel (const char *contentType)

Private Attributes

nsCString mSpec
nsIChannelmChannel
GnomeVFSHandle * mHandle
PRUint32 mBytesRemaining
nsresult mStatus
GList * mDirList
GList * mDirListPtr
nsCString mDirBuf
PRUint32 mDirBufCursor
PRPackedBool mDirOpen

Detailed Description

Definition at line 356 of file nsGnomeVFSProtocolHandler.cpp.


Constructor & Destructor Documentation

NS_DECL_ISUPPORTS NS_DECL_NSIINPUTSTREAM nsGnomeVFSInputStream::nsGnomeVFSInputStream ( const nsCString uriSpec) [inline]

Definition at line 373 of file nsGnomeVFSProtocolHandler.cpp.

{ Close(); }

Member Function Documentation

unsigned long nsIInputStream::available ( ) [inherited]
Returns:
number of bytes currently available in the stream
void nsIInputStream::close ( ) [inherited]

Close the stream.

GnomeVFSResult nsGnomeVFSInputStream::DoOpen ( ) [private]

Definition at line 412 of file nsGnomeVFSProtocolHandler.cpp.

{
  GnomeVFSResult rv;

  NS_ASSERTION(mHandle == nsnull, "already open");

  // Push a callback handler on the stack for this thread, so we can intercept
  // authentication requests from GnomeVFS.  We'll use the channel to get a
  // nsIAuthPrompt instance.

  gnome_vfs_module_callback_push(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
                                 AuthCallback, mChannel, NULL);

  // Query the mime type first (this could return NULL). 
  //
  // XXX We need to do this up-front in order to determine how to open the URI.
  //     Unfortunately, the error code GNOME_VFS_ERROR_IS_DIRECTORY is not
  //     always returned by gnome_vfs_open when we pass it a URI to a directory!
  //     Otherwise, we could have used that as a way to failover to opening the
  //     URI as a directory.  Also, it would have been ideal if
  //     gnome_vfs_get_file_info_from_handle were actually implemented by the
  //     smb:// module, since that would have allowed us to potentially save a
  //     round trip to the server to discover the mime type of the document in
  //     the case where gnome_vfs_open would have been used.  (Oh well!  /me
  //     throws hands up in the air and moves on...)

  GnomeVFSFileInfo info = {0};
  rv = gnome_vfs_get_file_info(mSpec.get(), &info, GNOME_VFS_FILE_INFO_DEFAULT);
  if (rv == GNOME_VFS_OK && info.type == GNOME_VFS_FILE_TYPE_DIRECTORY)
  {
    rv = gnome_vfs_directory_list_load(&mDirList, mSpec.get(),
                                       GNOME_VFS_FILE_INFO_DEFAULT);

    LOG(("gnomevfs: gnome_vfs_directory_list_load returned %d (%s) [spec=\"%s\"]\n",
        rv, gnome_vfs_result_to_string(rv), mSpec.get()));
  }
  else
  {
    rv = gnome_vfs_open(&mHandle, mSpec.get(), GNOME_VFS_OPEN_READ);

    LOG(("gnomevfs: gnome_vfs_open returned %d (%s) [spec=\"%s\"]\n",
        rv, gnome_vfs_result_to_string(rv), mSpec.get()));
  }

  gnome_vfs_module_callback_pop(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION);

  if (rv == GNOME_VFS_OK)
  {
    if (mHandle)
    {
      // Here we set the content type of the channel to the value of the mime
      // type determined by GnomeVFS.  However, if GnomeVFS is telling us that
      // the document is binary, we'll ignore that and keep the channel's
      // content type unspecified.  That will enable our content type sniffing
      // algorithms.  This should provide more consistent mime type handling.

      if (info.mime_type && (strcmp(info.mime_type, APPLICATION_OCTET_STREAM) != 0))
        SetContentTypeOfChannel(info.mime_type);

      // XXX truncates size from 64-bit to 32-bit
      mBytesRemaining = (PRUint32) info.size;

      // Update the content length attribute on the channel.  We do this
      // synchronously without proxying.  This hack is not as bad as it looks!
      if (mBytesRemaining != PR_UINT32_MAX)
        mChannel->SetContentLength(mBytesRemaining);
    }
    else
    {
      mDirOpen = PR_TRUE;

      // Sort mDirList
      mDirList = g_list_sort(mDirList, FileInfoComparator);
      mDirListPtr = mDirList;

      // Write base URL (make sure it ends with a '/')
      mDirBuf.Append(NS_LITERAL_CSTRING("300: ") + mSpec);
      if (mSpec.Last() != '/')
        mDirBuf.Append('/');
      mDirBuf.Append('\n');

      // Write column names
      mDirBuf.Append("200: filename content-length last-modified file-type\n");

      // Write charset (assume UTF-8)
      // XXX is this correct?
      mDirBuf.Append("301: UTF-8\n");

      SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT);
    }
  }

  gnome_vfs_file_info_clear(&info);
  return rv;
}

Here is the call graph for this function:

GnomeVFSResult nsGnomeVFSInputStream::DoRead ( char *  aBuf,
PRUint32  aCount,
PRUint32 aCountRead 
) [private]

Definition at line 509 of file nsGnomeVFSProtocolHandler.cpp.

{
  GnomeVFSResult rv;

  if (mHandle)
  {
    GnomeVFSFileSize bytesRead;
    rv = gnome_vfs_read(mHandle, aBuf, aCount, &bytesRead);
    if (rv == GNOME_VFS_OK)
    {
      *aCountRead = (PRUint32) bytesRead;
      mBytesRemaining -= *aCountRead;
    }
  }
  else if (mDirOpen)
  {
    rv = GNOME_VFS_OK;

    while (aCount && rv != GNOME_VFS_ERROR_EOF)
    {
      // Copy data out of our buffer
      PRUint32 bufLen = mDirBuf.Length() - mDirBufCursor;
      if (bufLen)
      {
        PRUint32 n = PR_MIN(bufLen, aCount);
        memcpy(aBuf, mDirBuf.get() + mDirBufCursor, n);
        *aCountRead += n;
        aBuf += n;
        aCount -= n;
        mDirBufCursor += n;
      }

      if (!mDirListPtr)    // Are we at the end of the directory list?
      {
        rv = GNOME_VFS_ERROR_EOF;
      }
      else if (aCount)     // Do we need more data?
      {
        GnomeVFSFileInfo *info = (GnomeVFSFileInfo *) mDirListPtr->data;

        // Prune '.' and '..' from directory listing.
        if (info->name[0] == '.' &&
               (info->name[1] == '\0' ||
                   (info->name[1] == '.' && info->name[2] == '\0')))
        {
          mDirListPtr = mDirListPtr->next;
          continue;
        }

        mDirBuf.Assign("201: ");

        // The "filename" field
        char *escName = nsEscape(info->name, url_Path);
        if (escName)
        {
          mDirBuf.Append(escName);
          mDirBuf.Append(' ');
          nsMemory::Free(escName);
        }

        // The "content-length" field
        // XXX truncates size from 64-bit to 32-bit
        mDirBuf.AppendInt(PRInt32(info->size));
        mDirBuf.Append(' ');

        // The "last-modified" field
        // 
        // NSPR promises: PRTime is compatible with time_t
        // we just need to convert from seconds to microseconds
        PRExplodedTime tm;
        PRTime pt = ((PRTime) info->mtime) * 1000000;
        PR_ExplodeTime(pt, PR_GMTParameters, &tm);
        {
          char buf[64];
          PR_FormatTimeUSEnglish(buf, sizeof(buf),
              "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm);
          mDirBuf.Append(buf);
        }

        // The "file-type" field
        switch (info->type)
        {
          case GNOME_VFS_FILE_TYPE_REGULAR:
            mDirBuf.AppendLiteral("FILE ");
            break;
          case GNOME_VFS_FILE_TYPE_DIRECTORY:
            mDirBuf.AppendLiteral("DIRECTORY ");
            break;
          case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK:
            mDirBuf.AppendLiteral("SYMBOLIC-LINK ");
            break;
          default:
            break;
        }

        mDirBuf.Append('\n');

        mDirBufCursor = 0;
        mDirListPtr = mDirListPtr->next;
      }
    }
  }
  else
  {
    NS_NOTREACHED("reading from what?");
    rv = GNOME_VFS_ERROR_GENERIC;
  }

  return rv;
}

Here is the call graph for this function:

Returns:
true if stream is non-blocking
unsigned long nsIInputStream::read ( in charPtr  aBuf,
in unsigned long  aCount 
) [inherited]

Read data from the stream.

Parameters:
aBufthe buffer into which the data is to be read
aCountthe maximum number of bytes to be read
Returns:
number of bytes read (may be less than aCount).
0 if reached end of file
Exceptions:
NS_BASE_STREAM_WOULD_BLOCKif reading from the input stream would block the calling thread (non-blocking mode only)
<other-error>on failure
unsigned long nsIInputStream::readSegments ( in nsWriteSegmentFun  aWriter,
in voidPtr  aClosure,
in unsigned long  aCount 
) [inherited]

Low-level read method that has access to the stream's underlying buffer.

The writer function may be called multiple times for segmented buffers. ReadSegments is expected to keep calling the writer until either there is nothing left to read or the writer returns an error. ReadSegments should not call the writer with zero bytes to consume.

Parameters:
aWriterthe "consumer" of the data to be read
aClosureopaque parameter passed to writer
aCountthe maximum number of bytes to be read
Returns:
number of bytes read (may be less than aCount)
0 if reached end of file (or if aWriter refused to consume data)
Exceptions:
NS_BASE_STREAM_WOULD_BLOCKif reading from the input stream would block the calling thread (non-blocking mode only)
<other-error>on failure

NOTE: this function may be unimplemented if a stream has no underlying buffer (e.g., socket input stream).

Definition at line 375 of file nsGnomeVFSProtocolHandler.cpp.

    {
      // We need to hold an owning reference to our channel.  This is done
      // so we can access the channel's notification callbacks to acquire
      // a reference to a nsIAuthPrompt if we need to handle a GnomeVFS
      // authentication callback.
      //
      // However, the channel can only be accessed on the main thread, so
      // we have to be very careful with ownership.  Moreover, it doesn't
      // support threadsafe addref/release, so proxying is the answer.
      //
      // Also, it's important to note that this likely creates a reference
      // cycle since the channel likely owns this stream.  This reference
      // cycle is broken in our Close method.

      NS_ADDREF(mChannel = channel);
    }

Here is the call graph for this function:

Definition at line 650 of file nsGnomeVFSProtocolHandler.cpp.

{
  // We need to proxy this call over to the main thread.  We post an
  // asynchronous event in this case so that we don't delay reading data, and
  // we know that this is safe to do since the channel's reference will be
  // released asynchronously as well.  We trust the ordering of the main
  // thread's event queue to protect us against memory corruption.

  nsresult rv;
  nsCOMPtr<nsIEventQueue> eventQ;
  rv = NS_GetMainEventQ(getter_AddRefs(eventQ));
  if (NS_FAILED(rv))
    return rv;

  nsGnomeVFSSetContentTypeEvent *ev =
      new nsGnomeVFSSetContentTypeEvent(mChannel, contentType);
  if (!ev)
  {
    rv = NS_ERROR_OUT_OF_MEMORY;
  }
  else
  {
    rv = eventQ->PostEvent(ev);
    if (NS_FAILED(rv))
      PL_DestroyEvent(ev);
  }
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 402 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 400 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 406 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 407 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 404 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 405 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 408 of file nsGnomeVFSProtocolHandler.cpp.

GnomeVFSHandle* nsGnomeVFSInputStream::mHandle [private]

Definition at line 401 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 399 of file nsGnomeVFSProtocolHandler.cpp.

Definition at line 403 of file nsGnomeVFSProtocolHandler.cpp.


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