rv = NS_ERROR_NOT_AVAILABLE;
GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename,                                        const nsAString& aMajorType,                                        const nsAString& aMinorType,                                        nsHashtable& aTypeOptions,                                        nsAString& aHandler,                                        nsAString& aDescription,                                        nsAString& aMozillaFlags) {  nsresult rv = NS_OK;  PRBool more = PR_FALSE;    nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));  if (NS_FAILED(rv))    return rv;  rv = file->InitWithPath(aFilename);  if (NS_FAILED(rv))    return rv;  nsCOMPtr<nsIFileInputStream> mailcapFile(do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv));  if (NS_FAILED(rv))    return rv;  rv = mailcapFile->Init(file, -1, -1, PR_FALSE);  if (NS_FAILED(rv))    return rv;  nsCOMPtr<nsILineInputStream> mailcap (do_QueryInterface(mailcapFile, &rv));#ifdef DEBUG_bzbarsky  if (NS_FAILED(rv)) {    fprintf(stderr, "Interface trouble!\n\n");  }#endif // DEBUG_bzbarsky  if (NS_FAILED(rv)) {    return rv;  }  nsString entry, buffer;  entry.SetCapacity(128);  buffer.SetCapacity(80);  rv = mailcap->ReadLine(buffer, &more);  if (NS_FAILED(rv)) {    mailcapFile->Close();    return rv;  }  do {  // return on end-of-file in the loop    if (!buffer.IsEmpty() && buffer.First() != '#') {      entry.Append(buffer);      if (entry.Last() == '\\') {  // entry continues on next line        entry.Truncate(entry.Length()-1);        entry.Append(PRUnichar(' ')); // in case there is no trailing whitespace on this line      } else {  // we have a full entry in entry.  Check it for the type        nsAString::const_iterator semicolon_iter,                                  start_iter, end_iter,                                  majorTypeStart, majorTypeEnd,                                  minorTypeStart, minorTypeEnd;        entry.BeginReading(start_iter);        entry.EndReading(end_iter);        semicolon_iter = start_iter;        FindSemicolon(semicolon_iter, end_iter);        if (semicolon_iter != end_iter) { // we have something resembling a valid entry          rv = ParseMIMEType(start_iter, majorTypeStart, majorTypeEnd,                             minorTypeStart, minorTypeEnd, semicolon_iter);          if (NS_SUCCEEDED(rv) &&              Substring(majorTypeStart,                        majorTypeEnd).Equals(aMajorType,                                             nsCaseInsensitiveStringComparator()) &&              (Substring(minorTypeStart,                         minorTypeEnd).Equals(NS_LITERAL_STRING("*")) ||               Substring(minorTypeStart,                         minorTypeEnd).Equals(aMinorType,                                              nsCaseInsensitiveStringComparator()))) { // we have a match            PRBool match = PR_TRUE;            ++semicolon_iter;             // point at the first char past the semicolon            start_iter = semicolon_iter;  // handler string starts here            FindSemicolon(semicolon_iter, end_iter);            while (start_iter != semicolon_iter &&                   nsCRT::IsAsciiSpace(*start_iter)) {              ++start_iter;            }#ifdef DEBUG_bzbarsky            fprintf(stderr, "The real handler is: %s\n", NS_ConvertUCS2toUTF8(Substring(start_iter, semicolon_iter)).get());#endif // DEBUG_bzbarsky                          // XXX ugly hack.  Just grab the executable name            nsAString::const_iterator end_handler_iter = semicolon_iter;            nsAString::const_iterator end_executable_iter = start_iter;            while (end_executable_iter != end_handler_iter &&                   !nsCRT::IsAsciiSpace(*end_executable_iter)) {              ++end_executable_iter;            }            // XXX End ugly hack                        aHandler = Substring(start_iter, end_executable_iter);                        nsAString::const_iterator start_option_iter, end_optionname_iter, equal_sign_iter;            PRBool equalSignFound;            while (match &&                   semicolon_iter != end_iter &&                   ++semicolon_iter != end_iter) { // there are options left and we still match              start_option_iter = semicolon_iter;              // skip over leading whitespace              while (start_option_iter != end_iter &&                     nsCRT::IsAsciiSpace(*start_option_iter)) {                ++start_option_iter;              }              if (start_option_iter == end_iter) { // nothing actually here                break;              }              semicolon_iter = start_option_iter;              FindSemicolon(semicolon_iter, end_iter);              equal_sign_iter = start_option_iter;              equalSignFound = PR_FALSE;              while (equal_sign_iter != semicolon_iter && !equalSignFound) {                switch(*equal_sign_iter) {                case '\\':                  equal_sign_iter.advance(2);                  break;                case '=':                  equalSignFound = PR_TRUE;                  break;                default:                  ++equal_sign_iter;                  break;                }              }              end_optionname_iter = start_option_iter;              // find end of option name              while (end_optionname_iter != equal_sign_iter &&                     !nsCRT::IsAsciiSpace(*end_optionname_iter)) {                ++end_optionname_iter;              }                                   nsDependentSubstring optionName(start_option_iter, end_optionname_iter);              if (equalSignFound) {                // This is an option that has a name and value                if (optionName.Equals(NS_LITERAL_STRING("description"))) {                  aDescription = Substring(++equal_sign_iter, semicolon_iter);                } else if (optionName.Equals(NS_LITERAL_STRING("x-mozilla-flags"))) {                  aMozillaFlags = Substring(++equal_sign_iter, semicolon_iter);                } else if (optionName.Equals(NS_LITERAL_STRING("test"))) {                  nsCAutoString testCommand;                  rv = UnescapeCommand(Substring(++equal_sign_iter, semicolon_iter),                                       aMajorType,                                       aMinorType,                                       aTypeOptions,                                       testCommand);#ifdef DEBUG_bzbarsky                  fprintf(stderr, "Running Test: %s\n", testCommand.get());#endif                  if (NS_SUCCEEDED(rv) && system(testCommand.get()) != 0) {                    match = PR_FALSE;                  }                }              } else {                // This is an option that just has a name but no value (eg "copiousoutput")              }            }                        if (match) { // we did not fail any test clauses; all is good              // get out of here              mailcapFile->Close();              return NS_OK;            } else { // pretend that this match never happened              aDescription.Truncate();              aMozillaFlags.Truncate();              aHandler.Truncate();            }          }        }        // zero out the entry for the next cycle        entry.Truncate();      }        }    if (!more) {      break;    }    rv = mailcap->ReadLine(buffer, &more);  } while (NS_SUCCEEDED(rv));  mailcapFile->Close();  return rv;}