Пример #1
0
void
UrlWrapper::ArgvReceived(int32 argc, char** argv)
{
    if (argc <= 1)
        return;

    const char* failc = " || read -p 'Press any key'";
    const char* pausec = " ; read -p 'Press any key'";
    char* args[] = { (char *)"/bin/sh", (char *)"-c", NULL, NULL};
    status_t err;

    BUrl url(argv[1]);

    BString full = BUrl(url).SetProtocol(BString()).UrlString();
    BString proto = url.Protocol();
    BString host = url.Host();
    BString port = BString() << url.Port();
    BString user = url.UserInfo();
    BString pass = url.Password();
    BString path = url.Path();

    if (!url.IsValid()) {
        fprintf(stderr, "malformed url: '%s'\n", url.UrlString().String());
        return;
    }

    // XXX: debug
    PRINT(("PROTO='%s'\n", proto.String()));
    PRINT(("HOST='%s'\n", host.String()));
    PRINT(("PORT='%s'\n", port.String()));
    PRINT(("USER='******'\n", user.String()));
    PRINT(("PASS='******'\n", pass.String()));
    PRINT(("PATH='%s'\n", path.String()));

    if (proto == "about") {
        app_info info;
        BString sig;
        // BUrl could get an accessor for the full - proto part...
        sig = host << "/" << path;
        BMessage msg(B_ABOUT_REQUESTED);
        if (be_roster->GetAppInfo(sig.String(), &info) == B_OK) {
            BMessenger msgr(sig.String());
            msgr.SendMessage(&msg);
            return;
        }
        if (be_roster->Launch(sig.String(), &msg) == B_OK)
            return;
        be_roster->Launch("application/x-vnd.Haiku-About");
        return;
    }

    if (proto == "telnet") {
        BString cmd("telnet ");
        if (url.HasUserInfo())
            cmd << "-l " << user << " ";
        cmd << host;
        if (url.HasPort())
            cmd << " " << port;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << failc;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        return;
    }

    // see draft:
    // http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/
    if (proto == "ssh") {
        BString cmd("ssh ");

        if (url.HasUserInfo())
            cmd << "-l " << user << " ";
        if (url.HasPort())
            cmd << "-oPort=" << port << " ";
        cmd << host;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << failc;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        // TODO: handle errors
        return;
    }

    if (proto == "ftp") {
        BString cmd("ftp ");

        cmd << proto << "://";
        /*
        if (user.Length())
        	cmd << "-l " << user << " ";
        cmd << host;
        */
        cmd << full;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << failc;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        // TODO: handle errors
        return;
    }

    if (proto == "sftp") {
        BString cmd("sftp ");

        //cmd << url;
        if (url.HasPort())
            cmd << "-oPort=" << port << " ";
        if (url.HasUserInfo())
            cmd << user << "@";
        cmd << host;
        if (url.HasPath())
            cmd << ":" << path;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << failc;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        // TODO: handle errors
        return;
    }

    if (proto == "finger") {
        BString cmd("/bin/finger ");

        if (url.HasUserInfo())
            cmd << user;
        if (url.HasHost() == 0)
            host = "127.0.0.1";
        cmd << "@" << host;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << pausec;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        // TODO: handle errors
        return;
    }

    if (proto == "http" || proto == "https" /*|| proto == "ftp"*/) {
        BString cmd("/bin/wget ");

        //cmd << url;
        cmd << proto << "://";
        if (url.HasUserInfo())
            cmd << user << "@";
        cmd << full;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << pausec;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        // TODO: handle errors
        return;
    }

    if (proto == "file") {
        BMessage m(B_REFS_RECEIVED);
        entry_ref ref;
        _DecodeUrlString(path);
        if (get_ref_for_path(path.String(), &ref) < B_OK)
            return;
        m.AddRef("refs", &ref);
        be_roster->Launch(kTrackerSig, &m);
        return;
    }

    // XXX:TODO: split options
    if (proto == "query") {
        // mktemp ?
        BString qname("/tmp/query-url-temp-");
        qname << getpid() << "-" << system_time();
        BFile query(qname.String(), O_CREAT|O_EXCL);
        // XXX: should check for failure

        BString s;
        int32 v;

        _DecodeUrlString(full);
        // TODO: handle options (list of attrs in the column, ...)

        v = 'qybF'; // QuerY By Formula XXX: any #define for that ?
        query.WriteAttr("_trk/qryinitmode", B_INT32_TYPE, 0LL, &v, sizeof(v));
        s = "TextControl";
        query.WriteAttr("_trk/focusedView", B_STRING_TYPE, 0LL, s.String(),
                        s.Length()+1);
        s = full;
        PRINT(("QUERY='%s'\n", s.String()));
        query.WriteAttr("_trk/qryinitstr", B_STRING_TYPE, 0LL, s.String(),
                        s.Length()+1);
        query.WriteAttr("_trk/qrystr", B_STRING_TYPE, 0LL, s.String(),
                        s.Length()+1);
        s = "application/x-vnd.Be-query";
        query.WriteAttr("BEOS:TYPE", 'MIMS', 0LL, s.String(), s.Length()+1);


        BEntry e(qname.String());
        entry_ref er;
        if (e.GetRef(&er) >= B_OK)
            be_roster->Launch(&er);
        return;
    }

    if (proto == "sh") {
        BString cmd(full);
        if (_Warn(url.UrlString()) != B_OK)
            return;
        PRINT(("CMD='%s'\n", cmd.String()));
        cmd << pausec;
        args[2] = (char*)cmd.String();
        be_roster->Launch(kTerminalSig, 3, args);
        // TODO: handle errors
        return;
    }

    if (proto == "beshare") {
        team_id team;
        BMessenger msgr(kBeShareSig);
        // if no instance is running, or we want a specific server, start it.
        if (!msgr.IsValid() || url.HasHost()) {
            be_roster->Launch(kBeShareSig, (BMessage*)NULL, &team);
            msgr = BMessenger(NULL, team);
        }
        if (url.HasHost()) {
            BMessage mserver('serv');
            mserver.AddString("server", host);
            msgr.SendMessage(&mserver);

        }
        if (url.HasPath()) {
            BMessage mquery('quer');
            mquery.AddString("query", path);
            msgr.SendMessage(&mquery);
        }
        // TODO: handle errors
        return;
    }

    if (proto == "icq" || proto == "msn") {
        // TODO
        team_id team;
        be_roster->Launch(kIMSig, (BMessage*)NULL, &team);
        BMessenger msgr(NULL, team);
        if (url.HasHost()) {
            BMessage mserver(B_REFS_RECEIVED);
            mserver.AddString("server", host);
            msgr.SendMessage(&mserver);

        }
        // TODO: handle errors
        return;
    }

    if (proto == "mms" || proto == "rtp" || proto == "rtsp") {
        args[0] = (char*)url.UrlString().String();
        be_roster->Launch(kVLCSig, 1, args);
        return;
    }

    if (proto == "nfs") {
        BString parameter(host);
        _DecodeUrlString(path);
        if (url.HasPort())
            parameter << ":" << port;
        //XXX: should not always be absolute! FIXME
        parameter << ":/" << path;
        BString prettyPath(path);
        prettyPath.Remove(0, prettyPath.FindLast("/") + 1);
        if (path == "" || path == "/")
            prettyPath = "root";
        prettyPath << " on " << host;
        prettyPath.Prepend("/");
        if (mkdir(prettyPath.String(), 0755) < 0) {
            perror("mkdir");
            return;
        }
        dev_t volume;
        uint32 flags = 0;
        fprintf(stderr, "parms:'%s'\n", parameter.String());
        volume = fs_mount_volume(prettyPath.String(), NULL, "nfs4", flags,
                                 parameter.String());
        if (volume < B_OK) {
            fprintf(stderr, "fs_mount_volume: %s\n", strerror(volume));
            return;
        }

        BMessage m(B_REFS_RECEIVED);
        entry_ref ref;
        if (get_ref_for_path(prettyPath.String(), &ref) < B_OK)
            return;
        m.AddRef("refs", &ref);
        be_roster->Launch(kTrackerSig, &m);
        return;
    }

    if (proto == "doi") {
        BString url("http://dx.doi.org/");
        BString mimetype;

        url << full;
        BUrl u(url.String());
        args[0] = const_cast<char*>("urlwrapper"); //XXX
        args[1] = (char*)u.UrlString().String();
        args[2] = NULL;
        mimetype = kURLHandlerSigBase;
        mimetype += u.Protocol();

        err = be_roster->Launch(mimetype.String(), 1, args + 1);
        if (err != B_OK && err != B_ALREADY_RUNNING)
            err = be_roster->Launch(kAppSig, 1, args + 1);
        // TODO: handle errors
        return;
    }

    /*

    More ?
    cf. http://en.wikipedia.org/wiki/URI_scheme
    cf. http://www.iana.org/assignments/uri-schemes.html

    Audio: (SoundPlay specific, identical to http:// to a shoutcast server)

    vnc: ?
    irc: ?
    im: http://tools.ietf.org/html/rfc3860

    svn: handled by checkitout
    cvs: handled by checkitout
    git: handled by checkitout
    rsync: handled by checkitout - http://tools.ietf.org/html/rfc5781

    smb: cifsmount ?
    nfs: mount_nfs ? http://tools.ietf.org/html/rfc2224
    ipp: http://tools.ietf.org/html/rfc3510

    mailto: ? Mail & Beam both handle it already (not fully though).
    imap: to describe mail accounts ? http://tools.ietf.org/html/rfc5092
    pop: http://tools.ietf.org/html/rfc2384
    mid: cid: as per RFC 2392
    http://www.rfc-editor.org/rfc/rfc2392.txt query MAIL:cid
    message:<MID> http://daringfireball.net/2007/12/message_urls_leopard_mail

    itps: pcast: podcast: s//http/ + parse xml to get url to mp3 stream...
    audio: s//http:/ + default MediaPlayer
    -- see http://forums.winamp.com/showthread.php?threadid=233130

    gps: ? I should submit an RFC for that one :)

    webcal: (is http: to .ics file)

    data: (but it's dangerous)

    */


}
Пример #2
0
void
UrlWrapper::ArgvReceived(int32 argc, char** argv)
{
	if (argc <= 1)
		return;
	
	const char* failc = " || read -p 'Press any key'";
	const char* pausec = " ; read -p 'Press any key'";
	char* args[] = { (char *)"/bin/sh", (char *)"-c", NULL, NULL};

	BPrivate::Support::BUrl url(argv[1]);

	BString full = url.Full();
	BString proto = url.Proto();
	BString host = url.Host();
	BString port = url.Port();
	BString user = url.User();
	BString pass = url.Pass();
	BString path = url.Path();

	if (url.InitCheck() < 0) {
		fprintf(stderr, "malformed url: '%s'\n", url.String());
		return;
	}
	
	// XXX: debug
	PRINT(("PROTO='%s'\n", proto.String()));
	PRINT(("HOST='%s'\n", host.String()));
	PRINT(("PORT='%s'\n", port.String()));
	PRINT(("USER='******'\n", user.String()));
	PRINT(("PASS='******'\n", pass.String()));
	PRINT(("PATH='%s'\n", path.String()));

	if (proto == "telnet") {
		BString cmd("telnet ");
		if (url.HasUser())
			cmd << "-l " << user << " ";
		cmd << host;
		if (url.HasPort())
			cmd << " " << port;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << failc;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		return;
	}
	
	// see draft:
	// http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/
	if (proto == "ssh") {
		BString cmd("ssh ");
		
		if (url.HasUser())
			cmd << "-l " << user << " ";
		if (url.HasPort())
			cmd << "-oPort=" << port << " ";
		cmd << host;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << failc;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		// TODO: handle errors
		return;
	}

	if (proto == "ftp") {
		BString cmd("ftp ");
		
		/*
		if (user.Length())
			cmd << "-l " << user << " ";
		cmd << host;
		*/
		cmd << full;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << failc;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		// TODO: handle errors
		return;
	}
	
	if (proto == "sftp") {
		BString cmd("sftp ");
		
		//cmd << url;
		if (url.HasPort())
			cmd << "-oPort=" << port << " ";
		if (url.HasUser())
			cmd << user << "@";
		cmd << host;
		if (url.HasPath())
			cmd << ":" << path;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << failc;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		// TODO: handle errors
		return;
	}

	if (proto == "finger") {
		BString cmd("/bin/finger ");
		
		if (url.HasUser())
			cmd << user;
		if (url.HasHost() == 0)
			host = "127.0.0.1";
		cmd << "@" << host;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << pausec;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		// TODO: handle errors
		return;
	}

	if (proto == "http") {
		BString cmd("/bin/wget ");
		
		//cmd << url;
		if (url.HasUser())
			cmd << user << "@";
		cmd << full;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << pausec;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		// TODO: handle errors
		return;
	}

	if (proto == "file") {
		BMessage m(B_REFS_RECEIVED);
		entry_ref ref;
		_DecodeUrlString(path);
		if (get_ref_for_path(path.String(), &ref) < B_OK)
			return;
		m.AddRef("refs", &ref);
		be_roster->Launch(kTrackerSig, &m);
		return;
	}

	// XXX:TODO: split options
	if (proto == "query") {
		// mktemp ?
		BString qname("/tmp/query-url-temp-");
		qname << getpid() << "-" << system_time();
		BFile query(qname.String(), O_CREAT|O_EXCL);
		// XXX: should check for failure
		
		BString s;
		int32 v;
		
		_DecodeUrlString(full);
		// TODO: handle options (list of attrs in the column, ...)

		v = 'qybF'; // QuerY By Formula XXX: any #define for that ?
		query.WriteAttr("_trk/qryinitmode", B_INT32_TYPE, 0LL, &v, sizeof(v));
		s = "TextControl";
		query.WriteAttr("_trk/focusedView", B_STRING_TYPE, 0LL, s.String(),
			s.Length()+1);
		s = full;
		PRINT(("QUERY='%s'\n", s.String()));
		query.WriteAttr("_trk/qryinitstr", B_STRING_TYPE, 0LL, s.String(),
			s.Length()+1);
		query.WriteAttr("_trk/qrystr", B_STRING_TYPE, 0LL, s.String(),
			s.Length()+1);
		s = "application/x-vnd.Be-query";
		query.WriteAttr("BEOS:TYPE", 'MIMS', 0LL, s.String(), s.Length()+1);
		

		BEntry e(qname.String());
		entry_ref er;
		if (e.GetRef(&er) >= B_OK)
			be_roster->Launch(&er);
		return;
	}

	if (proto == "sh") {
		BString cmd(full);
		if (_Warn(url.String()) != B_OK)
			return;
		PRINT(("CMD='%s'\n", cmd.String()));
		cmd << pausec;
		args[2] = (char*)cmd.String();
		be_roster->Launch(kTerminalSig, 3, args);
		// TODO: handle errors
		return;
	}

	if (proto == "beshare") {
		team_id team;
		BMessenger msgr(kBeShareSig);
		// if no instance is running, or we want a specific server, start it.
		if (!msgr.IsValid() || url.HasHost()) {
			be_roster->Launch(kBeShareSig, (BMessage*)NULL, &team);
			msgr = BMessenger(NULL, team);
		}
		if (url.HasHost()) {
			BMessage mserver('serv');
			mserver.AddString("server", host);
			msgr.SendMessage(&mserver);
			
		}
		if (url.HasPath()) {
			BMessage mquery('quer');
			mquery.AddString("query", path);
			msgr.SendMessage(&mquery);
		}
		// TODO: handle errors
		return;
	}

	if (proto == "icq" || proto == "msn") {
		// TODO
		team_id team;
		be_roster->Launch(kIMSig, (BMessage*)NULL, &team);
		BMessenger msgr(NULL, team);
		if (url.HasHost()) {
			BMessage mserver(B_REFS_RECEIVED);
			mserver.AddString("server", host);
			msgr.SendMessage(&mserver);
			
		}
		// TODO: handle errors
		return;
	}

	if (proto == "mms" || proto == "rtp" || proto == "rtsp") {
		args[0] = (char*)url.String();
		be_roster->Launch(kVLCSig, 1, args);
		return;
	}

	// Audio: ?

	// vnc: ?
	// irc: ?
	// 
	// svn: ?
	// cvs: ?
	// smb: cifsmount ?
	// nfs: mount_nfs ?
	//
	// mailto: ? Mail & Beam both handle it already (not fully though).
	//
	// mid: cid: as per RFC 2392
	// http://www.rfc-editor.org/rfc/rfc2392.txt query MAIL:cid
	//
	// itps: pcast: podcast: s//http/ + parse xml to get url to mp3 stream...
	// audio: s//http:/ + default MediaPlayer
	// -- see http://forums.winamp.com/showthread.php?threadid=233130
	//
	// gps: ? I should submit an RFC for that one :)

}
Пример #3
0
int main(int argc, char ** argv)
{
    interactive_signals();

    if (loadConfig(argc, argv, true) < 0) {
        // Fatal error loading config file
        return EXIT_CONFIG_ERROR;
    }

    if (daemon_flag) {
        int pid = daemonise();
        if (pid == -1) {
            return EXIT_FORK_ERROR;
        } else if (pid > 0) {
            return EXIT_SUCCESS;
        }
    }

    // If we are a daemon logging to syslog, we need to set it up.
    initLogger();

    // Initialise the persistance subsystem. If we have been built with
    // database support, this will open the various databases used to
    // store server data.
    if (database_flag) {
        Persistence * p = Persistence::instance();
        int dbstatus = p->init();
        if (dbstatus < 0) {
            database_flag = false;
            log(ERROR, "Error opening database. Database disabled.");
            if (dbstatus == DATABASE_TABERR) {
                log(INFO, "Database connection established, "
                          "but unable to create required tables.");
                log(INFO, "Please ensure that any obsolete database "
                          "tables have been removed.");
            } else {
                log(INFO, "Unable to connect to the RDBMS.");
                log(INFO, "Please ensure that the RDBMS is running, "
                          "the cyphesis database exists and is accessible "
                          "to the user running cyphesis.");
            }
            log(INFO, String::compose("To disable this message please run:\n\n"
                                      "    cyconfig --%1:usedatabase=false\n\n"
                                      "to permanently disable database usage.",
                                      instance));
        }
    }

    // If the restricted flag is set in the config file, then we
    // don't allow connecting users to create accounts. Accounts must
    // be created manually by the server administrator.
    if (readConfigItem("cyphesis","restricted", restricted_flag) == 0) {
        if (restricted_flag) {
            log(INFO, "Setting restricted mode.");
        }
    }

    readConfigItem("cyphesis","inittime", timeoffset);

    std::string mserver("metaserver.worldforge.org");
    readConfigItem("cyphesis", "metaserver", mserver);

    std::string serverName;
    if (readConfigItem("cyphesis","servername", serverName) != 0) {
        serverName = get_hostname();
    }

    std::string serverHostname("localhost");
    readConfigItem("slave","server", serverHostname);
    
    // Start up the python subsystem.
    init_python_api();

    { // scope for CommServer

    // Create commserver instance that will handle connections from clients.
    // The commserver will create the other server related objects, and the
    // world object pair (World + WorldRouter), and initialise the admin
    // account. The primary ruleset name is passed in so it
    // can be stored and queried by clients.
    WorldRouter world;

    // This ID is currently generated every time, but should perhaps be
    // persistent in future.
    std::string server_id, lobby_id;
    long int_id, lobby_int_id;

    if (((int_id = newId(server_id)) < 0) ||
        ((lobby_int_id = newId(lobby_id)) < 0)) {
        log(CRITICAL, "Unable to get server IDs from Database");
        return EXIT_DATABASE_ERROR;
    }

    ServerRouting server(world, ruleset, serverName,
                         server_id, int_id,
                         lobby_id, lobby_int_id);

    CommServer commServer(server);

    // This is where we should restore the database, before
    // the listen sockets are open. Unlike earlier code, we are
    // attempting to construct the internal state from the database,
    // not creating a new world using the contents of the database as a
    // template

    CommUnixListener * listener = new CommUnixListener(commServer,
          *new CommClientFactory<SlaveClientConnection>());
    if (listener->setup(slave_socket_name) != 0) {
        log(ERROR, "Could not create listen socket. Init failed.");
        return EXIT_SOCKET_ERROR;
    }
    commServer.addSocket(listener);

    std::string master_id;
    if (newId(master_id) < 0) {
        log(CRITICAL, "Unable to get master ID from Database");
        return EXIT_DATABASE_ERROR;
    }

    CommMaster * master = new CommMaster(commServer);
    if (master->connect(serverHostname) != 0) {
        log(ERROR, "Could not connect to master. Init failed.");
        return EXIT_SOCKET_ERROR;
    }
    master->setup(new Master(*master, commServer.m_server, master_id));
    commServer.addSocket(master);

    log(INFO, "Running");

    // Inform things that want to know that we are running.
    running();

    // Loop until the exit flag is set. The exit flag can be set anywhere in
    // the code easily.
    while (!exit_flag) {
        try {
            commServer.poll();
        }
        catch (...) {
            // It is hoped that commonly thrown exception, particularly
            // exceptions that can be caused  by external influences
            // should be caught close to where they are thrown. If
            // an exception makes it here then it should be debugged.
            log(ERROR, "Exception caught in main()");
        }
    }
    // exit flag has been set so we close down the databases, and indicate
    // to the metaserver (if we are using one) that this server is going down.
    // It is assumed that any preparation for the shutdown that is required
    // by the game has been done before exit flag was set.
    log(NOTICE, "Performing clean shutdown...");

    } // close scope of CommServer, which cause the destruction of the
      // server and world objects, and the entire world contents

    Persistence::instance()->shutdown();

    EntityBuilder::instance()->flushFactories();
    EntityBuilder::del();
    MindFactory::del();

    Inheritance::clear();

    // Shutdown the python interpretter. This frees lots of memory, and if
    // the malloc heap is in any way corrupt, a segfault is likely to
    // occur at this point. Previous occassions where pointers have been
    // deleted twice elsewhere in the code, have resulted in a segfault
    // at this point. AlRiddoch 10th November 2001
    shutdown_python_api();

    delete global_conf;

    log(INFO, "Clean shutdown complete.");
    return 0;
}