Exemple #1
0
 TestLaunchConfiguration(KUrl script) {
     c = new KConfig();
     cfg = c->group("launch");
     cfg.writeEntry("Server", script.host());
     cfg.writeEntry("Path", script.path());
     cfg.writeEntry("Arguments", script.query());
     KConfigGroup pmCfg = cfg.group("Path Mappings").group("0");
     pmCfg.writeEntry("Remote", KUrl(buildBaseUrl));
     pmCfg.writeEntry("Local", KUrl(QDir::currentPath()));
 }
 void SieveJob::schedule( Command command ) {
   switch ( command ) {
   case Get:
     kDebug() << "get(" << mUrl.prettyUrl() << ")";
     mJob = KIO::get( mUrl );
     connect( mJob, SIGNAL(data(KIO::Job*,const QByteArray&)),
              SLOT(slotData(KIO::Job*,const QByteArray&)) );
     break;
   case Put:
     kDebug() << "put(" << mUrl.prettyUrl() << ")";
     mJob = KIO::put( mUrl, 0600, KIO::Overwrite );
     connect( mJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)),
              SLOT(slotDataReq(KIO::Job*,QByteArray&)) );
     break;
   case Activate:
     kDebug() << "chmod(" << mUrl.prettyUrl() <<", 0700 )";
     mJob = KIO::chmod( mUrl, 0700 );
     break;
   case Deactivate:
     kDebug() << "chmod(" << mUrl.prettyUrl() <<", 0600 )";
     mJob = KIO::chmod( mUrl, 0600 );
     break;
   case SearchActive:
     kDebug() << "listDir(" << mUrl.prettyUrl() << ")";
     {
       KUrl url = mUrl;
       QString query = url.query(); //save query part, because KUrl::cd() erases it
       if ( !url.fileName().isEmpty() )
         url.cd("..");
       url.setQuery( query );
       kDebug() << "listDir's real URL:" << url.prettyUrl();
       mJob = KIO::listDir( url );
       connect( mJob, SIGNAL(entries(KIO::Job*,const KIO::UDSEntryList&)),
                SLOT(slotEntries(KIO::Job*,const KIO::UDSEntryList&)) );
       break;
     }
   case List:
     kDebug() << "listDir(" << mUrl.prettyUrl() << ")";
     {
       mJob = KIO::listDir( mUrl );
       connect( mJob, SIGNAL( entries(KIO::Job *, const KIO::UDSEntryList & ) ),
                SLOT( slotEntries( KIO::Job *, const KIO::UDSEntryList & ) ) );
       break;
     }
   case Delete:
     kDebug() << "delete(" << mUrl.prettyUrl() << ")";
     mJob = KIO::del( mUrl );
     break;
   default:
     assert( 0 );
   }
   // common to all jobs:
   connect( mJob, SIGNAL(result(KJob*)), SLOT(slotResult(KJob*)) );
 }
// The opposite of parseURL
static QString splitURL( int mRealArgType, const KUrl& url )
{
  if ( mRealArgType == 33 ) { // LDAP server
    // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
    Q_ASSERT( url.protocol() == "ldap" );
    return urlpart_encode( url.host() ) + ':' +
      ( url.port() != -1 ? QString::number( url.port() ) : QString() ) + ':' + // -1 is used for default ports, omit
      urlpart_encode( url.user() ) + ':' +
      urlpart_encode( url.pass() ) + ':' +
      // KUrl automatically encoded the query (e.g. for spaces inside it),
      // so decode it before writing it out to gpgconf (issue119)
      urlpart_encode( KUrl::fromPercentEncoding( url.query().mid(1).toLatin1() ) );
  }
  return url.path();
}
Exemple #4
0
  Request Request::fromURL( const KUrl & url ) {
    Request request;

    const QStringList query = url.query().mid(1).split( QLatin1Char('&') );
#ifndef NDEBUG
    kDebug(7112) << "Parsing request from query:\n" << query.join( QLatin1String("\n") );
#endif
    for ( QStringList::const_iterator it = query.begin() ; it != query.end() ; ++it ) {
      int equalsPos = (*it).indexOf( QLatin1Char('=') );
      if ( equalsPos <= 0 )
        continue;

      const QString key = (*it).left( equalsPos ).toLower();
      const QString value = QUrl::fromPercentEncoding( (*it).mid( equalsPos + 1 ).toLatin1() ); //krazy:exclude=qclasses

      if ( key == QLatin1String("to") )
        request.addTo( value );
      else if ( key == QLatin1String("cc") )
        request.addCc( value );
      else if ( key == QLatin1String("bcc") )
        request.addBcc( value );
      else if ( key == QLatin1String("headers") ) {
        request.setEmitHeaders( value == QLatin1String("0") );
        request.setEmitHeaders( false ); // ### ???
      }
      else if ( key == QLatin1String("subject") )
        request.setSubject( value );
      else if ( key == QLatin1String("from") )
        request.setFromAddress( value );
      else if ( key == QLatin1String("profile") )
        request.setProfileName( value );
      else if ( key == QLatin1String("hostname") )
        request.setHeloHostname( value );
      else if ( key == QLatin1String("body") )
        request.set8BitBody( value.toUpper() == QLatin1String("8BIT") );
      else if ( key == QLatin1String("size") )
        request.setSize( value.toUInt() );
      else
        kWarning(7112) << "while parsing query: unknown query item \""
                       << key << "\" with value \"" << value << "\"" << endl;
    }

    return request;
  }
Exemple #5
0
/**
 * List the contents of a directory.
 */
void LDAPProtocol::listDir( const KUrl &_url )
{
  int ret, ret2, id, id2;
  unsigned long total=0;
  QStringList att,saveatt;
  LdapUrl usrc(_url),usrc2;
  bool critical = true;
  bool isSub = ( usrc.extension( "x-dir", critical ) == "sub" );

  kDebug(7125) << "listDir(" << _url << ")";

  changeCheck( usrc );
  if ( !mConnected ) {
    finished();
    return;
  }
  usrc2 = usrc;

  saveatt = usrc.attributes();
  // look up the entries
  if ( isSub ) {
    att.append("dn");
    usrc.setAttributes(att);
  }
  if ( _url.query().isEmpty() ) usrc.setScope( LdapUrl::One );

  if ( (id = mOp.search( usrc.dn(), usrc.scope(), usrc.filter(), usrc.attributes() )) == -1 ) {
    LDAPErr();
    return;
  }

  usrc.setAttributes( QStringList() << "" );
  usrc.setExtension( "x-dir", "base" );
  // publish the results
  UDSEntry uds;

  while( true ) {
    ret = mOp.waitForResult( id, -1 );
    if ( ret == -1 || mConn.ldapErrorCode() != KLDAP_SUCCESS ) {
      LDAPErr();
      return;
    }
    if ( ret == LdapOperation::RES_SEARCH_RESULT ) break;
    if ( ret != LdapOperation::RES_SEARCH_ENTRY ) continue;
    kDebug(7125) << " ldap_result: " << ret;

    total++;
    uds.clear();

    LDAPEntry2UDSEntry( mOp.object().dn(), uds, usrc );
    listEntry( uds, false );
//      processedSize( total );
    kDebug(7125) << " total: " << total << " " << usrc.prettyUrl();

    // publish the sub-directories (if dirmode==sub)
    if ( isSub ) {
      LdapDN dn = mOp.object().dn();
      usrc2.setDn( dn );
      usrc2.setScope( LdapUrl::One );
      usrc2.setAttributes( saveatt );
      usrc2.setFilter( usrc.filter() );
      kDebug(7125) << "search2 " << dn.toString();
      if ( (id2 = mOp.search( dn, LdapUrl::One, QString(), att )) != -1 ) {
        while ( true ) {
          kDebug(7125) << " next result ";
          ret2 = mOp.waitForResult( id2, -1 );
          if ( ret2 == -1 || ret2 == LdapOperation::RES_SEARCH_RESULT ) break;
          if ( ret2 == LdapOperation::RES_SEARCH_ENTRY ) {
            LDAPEntry2UDSEntry( dn, uds, usrc2, true );
            listEntry( uds, false );
            total++;
            mOp.abandon( id2 );
            break;
          }
        }
      }
    }
  }

//  totalSize( total );

  uds.clear();
  listEntry( uds, true );
  // we are done
  finished();
}
Exemple #6
0
void CgiProtocol::get( const KUrl& url )
{
  kDebug(7124) << "CgiProtocol::get()";
  kDebug(7124) << " URL: " << url.url();
#if 0
  kDebug(7124) << " Path: " << url.path();
  kDebug(7124) << " Query: " << url.query();
  kDebug(7124) << " Protocol: " << url.protocol();
  kDebug(7124) << " Filename: " << url.filename();
#endif
  QByteArray protocol = "SERVER_PROTOCOL=HTTP";
  putenv( protocol.data() );

  QByteArray requestMethod = "REQUEST_METHOD=GET";
  putenv( requestMethod.data() );

  QByteArray query = url.query().mid( 1 ).toLocal8Bit();
  query.prepend( "QUERY_STRING=" );
  putenv( query.data() );

  QString path = url.path();

  QString file;

  int pos = path.lastIndexOf('/');
  if ( pos >= 0 ) file = path.mid( pos + 1 );
  else file = path;

  QString cmd;

  bool stripHeader = false;
  bool forwardFile = true;

  QStringList::ConstIterator it;
  for( it = mCgiPaths.constBegin(); it != mCgiPaths.constEnd(); ++it ) {
    cmd = *it;
    if ( !(*it).endsWith('/') )
        cmd += '/';
    cmd += file;
    if ( KStandardDirs::exists( cmd ) ) {
      forwardFile = false;
      stripHeader = true;
      break;
    }
  }

  FILE *fd;

  if ( forwardFile ) {
    kDebug(7124) << "Forwarding to '" << path << "'";

    QByteArray filepath = QFile::encodeName( path );

    fd = fopen( filepath.data(), "r" );

    if ( !fd ) {
      kDebug(7124) << "Error opening '" << filepath << "'";
      error(KIO::ERR_CANNOT_OPEN_FOR_READING, path);
      return;
    }
  } else {
    kDebug(7124) << "Cmd: " << cmd;

    fd = popen( QFile::encodeName(KShell::quoteArg( cmd )).data(), "r" );

    if ( !fd ) {
      kDebug(7124) << "Error running '" << cmd << "'";
      error( KIO::ERR_CANNOT_OPEN_FOR_READING, cmd );
      return;
    }
  }

  char buffer[ 4090 ];

  while ( !feof( fd ) )
  {
    int n = fread( buffer, 1, 2048, fd );

    if ( n == -1 )
    {
      // ERROR
      if ( forwardFile ) {
        fclose( fd );
      } else {
        pclose( fd );
      }
      return;
    }

    buffer[n] = 0;

    if ( stripHeader ) {
      QByteArray output = buffer; // this assumes buffer is text and not binary
      int colon = output.indexOf( ':' );
      int newline = output.indexOf( '\n' );
      int semicolon = output.lastIndexOf( ';', newline );
      int end;
      if ( semicolon < 0 ) end = newline;
      else end = semicolon;

#if 0
      kDebug(7124) << "  colon: " << colon;
      kDebug(7124) << "  newline: " << newline;
      kDebug(7124) << "  semicolon: " << semicolon;
      kDebug(7124) << "  end: " << end;
#endif

      // Set the charset meta data if one exists (BR# 241364).
      if (end == semicolon) {
          const int assignOp = output.indexOf('=', semicolon + 1);
          if (assignOp != -1) {
              const QByteArray charset (output.mid(assignOp+1, newline- assignOp -1).trimmed());
              kDebug(7124) << "Charset:" << charset;
              setMetaData(QLatin1String("charset"), charset.toLower());
          }
      }

      QByteArray contentType = output.mid( colon + 1, end - colon - 1 );

      contentType = contentType.trimmed().toLower();

      kDebug(7124) << "ContentType: '" << contentType << "'";

      mimeType( contentType );

      int start = output.indexOf( "\r\n\r\n" );
      if ( start >= 0 ) start += 4;
      else {
        start = output.indexOf( "\n\n" );
        if ( start >= 0 ) start += 2;
      }

      if ( start >= 0 ) output = output.mid( start );

      stripHeader = false;
      data( output );
    } else {
      data( QByteArray::fromRawData( buffer, n ) );
    }
  }

  if ( forwardFile ) {
    fclose( fd );
  } else {
    pclose( fd );
  }

  finished();

  kDebug(7124) << "CgiProtocol::get - done";
}
Exemple #7
0
bool KShortUriFilter::filterUri( KUriFilterData& data ) const
{
 /*
  * Here is a description of how the shortURI deals with the supplied
  * data.  First it expands any environment variable settings and then
  * deals with special shortURI cases. These special cases are the "smb:"
  * URL scheme which is very specific to KDE, "#" and "##" which are
  * shortcuts for man:/ and info:/ protocols respectively. It then handles
  * local files.  Then it checks to see if the URL is valid and one that is
  * supported by KDE's IO system.  If all the above checks fails, it simply
  * lookups the URL in the user-defined list and returns without filtering
  * if it is not found. TODO: the user-defined table is currently only manually
  * hackable and is missing a config dialog.
  */

  KUrl url = data.uri();
  QString cmd = data.typedString();

  // WORKAROUND: Allow the use of '@' in the username component of a URL since
  // other browsers such as firefox in their infinite wisdom allow such blatant
  // violations of RFC 3986. BR# 69326/118413.
  if (cmd.count(QLatin1Char('@')) > 1) {
    const int lastIndex = cmd.lastIndexOf(QLatin1Char('@'));
    // Percent encode all but the last '@'.
    QString encodedCmd = QUrl::toPercentEncoding(cmd.left(lastIndex), ":/");
    encodedCmd += cmd.mid(lastIndex);
    KUrl u (encodedCmd);
    if (u.isValid()) {
      cmd = encodedCmd;
      url = u;
    }
  }

  const bool isMalformed = !url.isValid();
  QString protocol = url.protocol();

  kDebug(7023) << cmd;

  // Fix misparsing of "foo:80", QUrl thinks "foo" is the protocol and "80" is the path.
  // However, be careful not to do that for valid hostless URLs, e.g. file:///foo!
  if (!protocol.isEmpty() && url.host().isEmpty() && !url.path().isEmpty()
      && cmd.contains(':') && !KProtocolInfo::protocols().contains(protocol)) {
    protocol.clear();
  }

  //kDebug(7023) << "url=" << url << "cmd=" << cmd << "isMalformed=" << isMalformed;

  if (!isMalformed &&
      (protocol.length() == 4) &&
      (protocol != QLatin1String("http")) &&
      (protocol[0]=='h') &&
      (protocol[1]==protocol[2]) &&
      (protocol[3]=='p'))
  {
     // Handle "encrypted" URLs like: h++p://www.kde.org
     url.setProtocol( QLatin1String("http"));
     setFilteredUri( data, url);
     setUriType( data, KUriFilterData::NetProtocol );
     return true;
  }

  // TODO: Make this a bit more intelligent for Minicli! There
  // is no need to make comparisons if the supplied data is a local
  // executable and only the argument part, if any, changed! (Dawit)
  // You mean caching the last filtering, to try and reuse it, to save stat()s? (David)

  const QString starthere_proto = QL1S("start-here:");
  if (cmd.indexOf(starthere_proto) == 0 )
  {
    setFilteredUri( data, KUrl("system:/") );
    setUriType( data, KUriFilterData::LocalDir );
    return true;
  }

  // Handle MAN & INFO pages shortcuts...
  const QString man_proto = QL1S("man:");
  const QString info_proto = QL1S("info:");
  if( cmd[0] == '#' ||
      cmd.indexOf( man_proto ) == 0 ||
      cmd.indexOf( info_proto ) == 0 )
  {
    if( cmd.left(2) == QL1S("##") )
      cmd = QL1S("info:/") + cmd.mid(2);
    else if ( cmd[0] == '#' )
      cmd = QL1S("man:/") + cmd.mid(1);

    else if ((cmd==info_proto) || (cmd==man_proto))
      cmd+='/';

    setFilteredUri( data, KUrl( cmd ));
    setUriType( data, KUriFilterData::Help );
    return true;
  }

  // Detect UNC style (aka windows SMB) URLs
  if ( cmd.startsWith( QLatin1String( "\\\\") ) )
  {
    // make sure path is unix style
    cmd.replace('\\', '/');
    cmd.prepend( QLatin1String( "smb:" ) );
    setFilteredUri( data, KUrl( cmd ));
    setUriType( data, KUriFilterData::NetProtocol );
    return true;
  }

  bool expanded = false;

  // Expanding shortcut to HOME URL...
  QString path;
  QString ref;
  QString query;
  QString nameFilter;

  if (KUrl::isRelativeUrl(cmd) && QDir::isRelativePath(cmd)) {
     path = cmd;
     //kDebug(7023) << "path=cmd=" << path;
  } else {
    if (url.isLocalFile())
    {
      //kDebug(7023) << "hasRef=" << url.hasRef();
      // Split path from ref/query
      // but not for "/tmp/a#b", if "a#b" is an existing file,
      // or for "/tmp/a?b" (#58990)
      if( ( url.hasRef() || !url.query().isEmpty() )
           && !url.path().endsWith(QL1S("/")) ) // /tmp/?foo is a namefilter, not a query
      {
        path = url.path();
        ref = url.ref();
        //kDebug(7023) << "isLocalFile set path to " << stringDetails( path );
        //kDebug(7023) << "isLocalFile set ref to " << stringDetails( ref );
        query = url.query();
        if (path.isEmpty() && url.hasHost())
          path = '/';
      }
      else
      {
        path = cmd;
        //kDebug(7023) << "(2) path=cmd=" << path;
      }
    }
  }

  if( path[0] == '~' )
  {
    int slashPos = path.indexOf('/');
    if( slashPos == -1 )
      slashPos = path.length();
    if( slashPos == 1 )   // ~/
    {
      path.replace ( 0, 1, QDir::homePath() );
    }
    else // ~username/
    {
      const QString userName (path.mid( 1, slashPos-1 ));
      KUser user (userName);
      if( user.isValid() && !user.homeDir().isEmpty())
      {
        path.replace (0, slashPos, user.homeDir());
      }
      else
      {
        if (user.isValid()) {
          setErrorMsg(data, i18n("<qt><b>%1</b> does not have a home folder.</qt>", userName));
        } else {
          setErrorMsg(data, i18n("<qt>There is no user called <b>%1</b>.</qt>", userName));
        }
        setUriType( data, KUriFilterData::Error );
        // Always return true for error conditions so
        // that other filters will not be invoked !!
        return true;
      }
    }
    expanded = true;
  }
  else if ( path[0] == '$' ) {
    // Environment variable expansion.
    if ( sEnvVarExp.indexIn( path ) == 0 )
    {
      QByteArray exp = qgetenv( path.mid( 1, sEnvVarExp.matchedLength() - 1 ).toLocal8Bit().data() );
      if(! exp.isNull())
      {
        path.replace( 0, sEnvVarExp.matchedLength(), QString::fromLocal8Bit(exp.constData()) );
        expanded = true;
      }
    }
  }

  if ( expanded || cmd.startsWith( '/' ) )
  {
    // Look for #ref again, after $ and ~ expansion (testcase: $QTDIR/doc/html/functions.html#s)
    // Can't use KUrl here, setPath would escape it...
    const int pos = path.indexOf('#');
    if ( pos > -1 )
    {
      const QString newPath = path.left( pos );
      if ( QFile::exists( newPath ) )
      {
        ref = path.mid( pos + 1 );
        path = newPath;
        //kDebug(7023) << "Extracted ref: path=" << path << " ref=" << ref;
      }
    }
  }


  bool isLocalFullPath = (!path.isEmpty() && path[0] == '/');

  // Checking for local resource match...
  // Determine if "uri" is an absolute path to a local resource  OR
  // A local resource with a supplied absolute path in KUriFilterData
  const QString abs_path = data.absolutePath();

  const bool canBeAbsolute = (protocol.isEmpty() && !abs_path.isEmpty());
  const bool canBeLocalAbsolute = (canBeAbsolute && abs_path[0] =='/' && !isMalformed);
  bool exists = false;

  /*kDebug(7023) << "abs_path=" << abs_path
               << "protocol=" << protocol
               << "canBeAbsolute=" << canBeAbsolute
               << "canBeLocalAbsolute=" << canBeLocalAbsolute
               << "isLocalFullPath=" << isLocalFullPath;*/

  KDE_struct_stat buff;
  if ( canBeLocalAbsolute )
  {
    QString abs = QDir::cleanPath( abs_path );
    // combine absolute path (abs_path) and relative path (cmd) into abs_path
    int len = path.length();
    if( (len==1 && path[0]=='.') || (len==2 && path[0]=='.' && path[1]=='.') )
        path += '/';
    //kDebug(7023) << "adding " << abs << " and " << path;
    abs = QDir::cleanPath(abs + '/' + path);
    //kDebug(7023) << "checking whether " << abs << " exists.";
    // Check if it exists
    if( KDE::stat( abs, &buff ) == 0 )
    {
      path = abs; // yes -> store as the new cmd
      exists = true;
      isLocalFullPath = true;
    }
  }

  if (isLocalFullPath && !exists && !isMalformed) {
    exists = ( KDE::stat( path, &buff ) == 0 );

    if ( !exists ) {
      // Support for name filter (/foo/*.txt), see also KonqMainWindow::detectNameFilter
      // If the app using this filter doesn't support it, well, it'll simply error out itself
      int lastSlash = path.lastIndexOf( '/' );
      if ( lastSlash > -1 && path.indexOf( ' ', lastSlash ) == -1 ) // no space after last slash, otherwise it's more likely command-line arguments
      {
        QString fileName = path.mid( lastSlash + 1 );
        QString testPath = path.left( lastSlash + 1 );
        if ( ( fileName.indexOf( '*' ) != -1 || fileName.indexOf( '[' ) != -1 || fileName.indexOf( '?' ) != -1 )
           && KDE::stat( testPath, &buff ) == 0 )
        {
          nameFilter = fileName;
          //kDebug(7023) << "Setting nameFilter to " << nameFilter;
          path = testPath;
          exists = true;
        }
      }
    }
  }

  //kDebug(7023) << "path =" << path << " isLocalFullPath=" << isLocalFullPath << " exists=" << exists;
  if( exists )
  {
    KUrl u;
    u.setPath(path);
    //kDebug(7023) << "ref=" << stringDetails(ref) << " query=" << stringDetails(query);
    u.setRef(ref);
    u.setQuery(query);

    if (!KAuthorized::authorizeUrlAction( QLatin1String("open"), KUrl(), u))
    {
      // No authorization, we pretend it's a file will get
      // an access denied error later on.
      setFilteredUri( data, u );
      setUriType( data, KUriFilterData::LocalFile );
      return true;
    }

    // Can be abs path to file or directory, or to executable with args
    bool isDir = S_ISDIR( buff.st_mode );
    if( !isDir && access ( QFile::encodeName(path).data(), X_OK) == 0 )
    {
      //kDebug(7023) << "Abs path to EXECUTABLE";
      setFilteredUri( data, u );
      setUriType( data, KUriFilterData::Executable );
      return true;
    }

    // Open "uri" as file:/xxx if it is a non-executable local resource.
    if( isDir || S_ISREG( buff.st_mode ) )
    {
      //kDebug(7023) << "Abs path as local file or directory";
      if ( !nameFilter.isEmpty() )
        u.setFileName( nameFilter );
      setFilteredUri( data, u );
      setUriType( data, ( isDir ) ? KUriFilterData::LocalDir : KUriFilterData::LocalFile );
      return true;
    }

    // Should we return LOCAL_FILE for non-regular files too?
    kDebug(7023) << "File found, but not a regular file nor dir... socket?";
  }

  if( data.checkForExecutables())
  {
    // Let us deal with possible relative URLs to see
    // if it is executable under the user's $PATH variable.
    // We try hard to avoid parsing any possible command
    // line arguments or options that might have been supplied.
    QString exe = removeArgs( cmd );
    //kDebug(7023) << "findExe with" << exe;

    if (!KStandardDirs::findExe( exe ).isNull() )
    {
      //kDebug(7023) << "EXECUTABLE  exe=" << exe;
      setFilteredUri( data, KUrl::fromPath( exe ));
      // check if we have command line arguments
      if( exe != cmd )
          setArguments(data, cmd.right(cmd.length() - exe.length()));
      setUriType( data, KUriFilterData::Executable );
      return true;
    }
  }

  // Process URLs of known and supported protocols so we don't have
  // to resort to the pattern matching scheme below which can possibly
  // slow things down...
  if ( !isMalformed && !isLocalFullPath && !protocol.isEmpty() )
  {
    //kDebug(7023) << "looking for protocol " << protocol;
    if ( KProtocolInfo::isKnownProtocol( protocol ) )
    {
      setFilteredUri( data, url );
      if ( protocol == QL1S("man") || protocol == QL1S("help") )
        setUriType( data, KUriFilterData::Help );
      else
        setUriType( data, KUriFilterData::NetProtocol );
      return true;
    }
  }

  // Short url matches
  if ( !cmd.contains( ' ' ) )
  {
    // Okay this is the code that allows users to supply custom matches for
    // specific URLs using Qt's regexp class. This is hard-coded for now.
    // TODO: Make configurable at some point...
    Q_FOREACH(const URLHint& hint, m_urlHints)
    {
      if (hint.regexp.indexIn(cmd) == 0)
      {
        //kDebug(7023) << "match - prepending" << (*it).prepend;
        const QString cmdStr = hint.prepend + cmd;
        KUrl url(cmdStr);
        if (KProtocolInfo::isKnownProtocol(url))
        {
          setFilteredUri( data, url );
          setUriType( data, hint.type );
          return true;
        }
      }
    }

    // No protocol and not malformed means a valid short URL such as kde.org or
    // [email protected]. However, it might also be valid only because it lacks
    // the scheme component, e.g. www.kde,org (illegal ',' before 'org'). The
    // check below properly deciphers the difference between the two and sends
    // back the proper result.
    if (protocol.isEmpty() && isPotentialShortURL(cmd))
    {
      QString urlStr = data.defaultUrlScheme();
      if (urlStr.isEmpty())
          urlStr = m_strDefaultUrlScheme;

      const int index = urlStr.indexOf(QL1C(':'));
      if (index == -1 || !KProtocolInfo::isKnownProtocol(urlStr.left(index)))
        urlStr += QL1S("://");
      urlStr += cmd;

      KUrl url (urlStr);
      if (url.isValid())
      {
        setFilteredUri(data, url);
        setUriType(data, KUriFilterData::NetProtocol);
      }
      else if (KProtocolInfo::isKnownProtocol(url.protocol()))
      {
        setFilteredUri(data, data.uri());
        setUriType(data, KUriFilterData::Error);
      }
      return true;
    }
  }