Back to index

lightning-sunbird  0.9+nobinonly
nsURLHelperOSX.cpp File Reference
#include "nsURLHelper.h"
#include "nsEscape.h"
#include "nsILocalFile.h"
#include "nsVoidArray.h"
#include "nsReadableUtils.h"
#include <Files.h>

Go to the source code of this file.


static PRBool pathBeginsWithVolName (const nsACString &path, nsACString &firstPathComponent)
static nsresult convertHFSPathtoPOSIX (const nsACString &hfsPath, nsACString &posixPath)
static void SwapSlashColon (char *s)
nsresult net_GetURLSpecFromFile (nsIFile *aFile, nsACString &result)
nsresult net_GetFileFromURLSpec (const nsACString &aURL, nsIFile **result)

Function Documentation

static nsresult convertHFSPathtoPOSIX ( const nsACString &  hfsPath,
nsACString &  posixPath 
) [static]

Definition at line 93 of file nsURLHelperOSX.cpp.

  // Use CFURL to do the conversion. We don't want to do this by simply
  // using SwapSlashColon - we need the charset mapped from MacRoman
  // to UTF-8, and we need "/Volumes" (or whatever - Apple says this is subject to change)
  // prepended if the path is not on the boot drive.

  CFStringRef pathStrRef = CFStringCreateWithCString(NULL,
  if (!pathStrRef)
    return NS_ERROR_FAILURE;

  nsresult rv = NS_ERROR_FAILURE;
  CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL,
                              pathStrRef, kCFURLHFSPathStyle, true);
  if (urlRef) {
    UInt8 pathBuf[PATH_MAX];
    if (CFURLGetFileSystemRepresentation(urlRef, true, pathBuf, sizeof(pathBuf))) {
      posixPath = (char *)pathBuf;
      rv = NS_OK;
  if (urlRef)
  return rv;

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult net_GetFileFromURLSpec ( const nsACString &  aURL,
nsIFile **  result 

Definition at line 179 of file nsURLHelperOSX.cpp.

  // NOTE: See also the implementation in nsURLHelperUnix.cpp
  // This matches it except for the HFS path handling and file
  // system charset conversion.

  nsresult rv;

  nsCOMPtr<nsILocalFile> localFile;
  rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(localFile));
  if (NS_FAILED(rv))
    return rv;
  nsCAutoString directory, fileBaseName, fileExtension, path;
  PRBool bHFSPath = PR_FALSE;

  rv = net_ParseFileURL(aURL, directory, fileBaseName, fileExtension);
  if (NS_FAILED(rv))
    return rv;

  if (!directory.IsEmpty()) {
    NS_EscapeURL(directory, esc_Directory|esc_AlwaysCopy, path);

    // The canonical form of file URLs on OSX use POSIX paths:
    //   file:///path-name.
    // But, we still encounter file URLs that use HFS paths:
    //   file:///volume-name/path-name
    // Determine that here and normalize HFS paths to POSIX.
    nsCAutoString possibleVolName;
    if (pathBeginsWithVolName(directory, possibleVolName)) {        
      // Though we know it begins with a volume name, it could still
      // be a valid POSIX path if the boot drive is named "Mac HD"
      // and there is a directory "Mac HD" at its root. If such a
      // directory doesn't exist, we'll assume this is an HFS path.
      FSRef testRef;
      possibleVolName.Insert("/", 0);
      if (::FSPathMakeRef((UInt8*)possibleVolName.get(), &testRef, nsnull) != noErr)
        bHFSPath = PR_TRUE;

    if (bHFSPath) {
      // "%2F"s need to become slashes, while all other slashes need to
      // become colons. If we start out by changing "%2F"s to colons, we
      // can reply on SwapSlashColon() to do what we need
      path.ReplaceSubstring("%2F", ":");
      path.Cut(0, 1); // directory begins with '/'
      SwapSlashColon((char *)path.get());
      // At this point, path is an HFS path made using the same
      // algorithm as nsURLHelperMac. We'll convert to POSIX below.
  if (!fileBaseName.IsEmpty())
    NS_EscapeURL(fileBaseName, esc_FileBaseName|esc_AlwaysCopy, path);
  if (!fileExtension.IsEmpty()) {
    path += '.';
    NS_EscapeURL(fileExtension, esc_FileExtension|esc_AlwaysCopy, path);

  if (path.Length() != strlen(path.get()))

  if (bHFSPath)
    convertHFSPathtoPOSIX(path, path);

  // assuming path is encoded in the native charset
  rv = localFile->InitWithNativePath(path);
  if (NS_FAILED(rv))
    return rv;

  NS_ADDREF(*result = localFile);
  return NS_OK;

Here is the call graph for this function:

nsresult net_GetURLSpecFromFile ( nsIFile aFile,
nsACString &  result 

Definition at line 134 of file nsURLHelperOSX.cpp.

  // NOTE: This used to be identical to the implementation in 
  // nsURLHelperUnix.cpp, but with bug 278161 fixed, it's now
  // different because unlike on Unix, the file system charset 
  // is always UTF-8  on OS X.
  nsresult rv;
  nsCAutoString ePath;

  // construct URL spec from native file path
  rv = aFile->GetNativePath(ePath);
  if (NS_FAILED(rv))
    return rv;

  nsCAutoString escPath;
  NS_NAMED_LITERAL_CSTRING(prefix, "file://");
  // Escape the path with the directory mask
  if (NS_EscapeURL(ePath.get(), ePath.Length(), esc_Directory+esc_Forced, escPath))
    escPath.Insert(prefix, 0);
    escPath.Assign(prefix + ePath);

  // esc_Directory does not escape the semicolons, so if a filename 
  // contains semicolons we need to manually escape them.
  escPath.ReplaceSubstring(";", "%3b");

  // if this file references a directory, then we need to ensure that the
  // URL ends with a slash.  this is important since it affects the rules
  // for relative URL resolution when this URL is used as a base URL.
  // if the file does not exist, then we make no assumption about its type,
  // and simply leave the URL unmodified.
  if (escPath.Last() != '/') {
    PRBool dir;
    rv = aFile->IsDirectory(&dir);
    if (NS_SUCCEEDED(rv) && dir)
      escPath += '/';
  result = escPath;
  return NS_OK;

Here is the call graph for this function:

static PRBool pathBeginsWithVolName ( const nsACString &  path,
nsACString &  firstPathComponent 
) [static]

Definition at line 50 of file nsURLHelperOSX.cpp.

  // Return whether the 1st path component in path (escaped) is equal to the name
  // of a mounted volume. Return the 1st path component (unescaped) in any case.
  // This needs to be done as quickly as possible, so we cache a list of volume names.
  // XXX Register an event handler to detect drives being mounted/unmounted?
  static nsCStringArray gVolumeList; // We will leak this - one for the life of the app :-/

  // Cache a list of volume names
  if (!gVolumeList.Count()) {
    OSErr err;
    ItemCount volumeIndex = 1;
    do {
      HFSUniStr255 volName;
      FSRef rootDirectory;
      err = ::FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoNone, NULL, &volName, &rootDirectory);
      if (err == noErr) {
        NS_ConvertUTF16toUTF8 volNameStr(Substring((PRUnichar *)volName.unicode,
                                                   (PRUnichar *)volName.unicode + volName.length));
    } while (err == noErr);
  // Extract the first component of the path
  nsACString::const_iterator start;
  start.advance(1); // path begins with '/'
  nsACString::const_iterator directory_end;
  nsACString::const_iterator component_end(start);
  FindCharInReadable('/', component_end, directory_end);
  nsCAutoString flatComponent((Substring(start, component_end)));
  PRInt32 foundIndex = gVolumeList.IndexOf(flatComponent);
  firstPathComponent = flatComponent;
  return (foundIndex != -1);

Here is the call graph for this function:

Here is the caller graph for this function:

static void SwapSlashColon ( char *  s) [static]

Definition at line 122 of file nsURLHelperOSX.cpp.

  while (*s) {
    if (*s == '/')
      *s = ':';
    else if (*s == ':')
      *s = '/';

Here is the caller graph for this function: