diff --git a/src/bin/urlwrapper.cpp b/src/bin/urlwrapper.cpp index b3cf29ac53..8823bd79a0 100644 --- a/src/bin/urlwrapper.cpp +++ b/src/bin/urlwrapper.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,33 +9,164 @@ #include #include -#define PROTO "telnet" +#define HANDLE_FILE +#define HANDLE_SH +#define HANDLE_BESHARE +//#define HANDLE_IM +#define HANDLE_VLC -class TWApp : public BApplication +const char *kAppSig = "application/x-vnd.haiku.urlwrapper"; + +#ifdef __HAIKU__ +const char *kTerminalSig = "application/x-vnd.Haiku-Terminal"; +#else +const char *kTerminalSig = "application/x-vnd.Be-SHEL"; +#endif + +#ifdef HANDLE_FILE +const char *kTrackerSig = "application/x-vnd.Be-TRAK"; +#endif + +#ifdef HANDLE_BESHARE +const char *kBeShareSig = "application/x-vnd.Sugoi-BeShare"; +#endif + +#ifdef HANDLE_IM +const char *kIMSig = "application/x-vnd.m_eiman.sample_im_client"; +#endif + +#ifdef HANDLE_VLC +const char *kVLCSig = "application/x-vnd.videolan-vlc"; +#endif + +// TODO: make a Url class +class Url : public BString { +public: + Url(const char *url) : BString(url) { fStatus = ParseAndSplit(); }; + ~Url() {}; +status_t InitCheck() const { return fStatus; }; +status_t ParseAndSplit(); + +bool HasHost() const { return host.Length(); }; +bool HasPort() const { return port.Length(); }; +bool HasUser() const { return user.Length(); }; +bool HasPass() const { return pass.Length(); }; +bool HasPath() const { return path.Length(); }; +BString Proto() const { return BString(proto); }; +BString Host() const { return BString(host); }; +BString Port() const { return BString(port); }; +BString User() const { return BString(user); }; +BString Pass() const { return BString(pass); }; + +BString proto; +BString host; +BString port; +BString user; +BString pass; +BString path; +private: +status_t fStatus; +}; + +class UrlWrapperApp : public BApplication { public: - TWApp(); - ~TWApp(); -status_t SplitUrlHostUserPass(const char *url, BString &host, BString &user, BString &pass); + UrlWrapperApp(); + ~UrlWrapperApp(); +status_t SplitUrl(const char *url, BString &host, BString &port, BString &user, BString &pass, BString &path); +status_t UnurlString(BString &s); +status_t Warn(const char *url); virtual void ArgvReceived(int32 argc, char **argv); virtual void ReadyToRun(void); private: }; -const char *app_mime = "application/x-vnd.mmu_man.telnetwrapper"; -//const char *url_mime = "application/x-vnd.Be.URL.telnet"; -const char *url_mime = B_URL_TELNET; -const char *terminal_sig = "application/x-vnd.Be-SHEL"; - -TWApp::TWApp() : BApplication(app_mime) +// TODO: handle ":port" as well +// TODO: handle "/path" as well +// proto:[//]user:pass@host:port/path +status_t Url::ParseAndSplit() { - BMimeType mt(url_mime); + int32 v; + //host = *this; + BString left; +printf("s:%s\n", String()); + + v = FindFirst(":"); + if (v < 0) + return EINVAL; + + CopyInto(proto, 0, v); + CopyInto(left, v + 1, Length() - v); + if (left.FindFirst("//") == 0) + left.RemoveFirst("//"); + + // path part + v = left.FindFirst("/"); + if (v == 0 || proto == "file") { + path = left; +printf("path:%s\n", path.String()); + return 0; + } + + if (v > -1) { + left.MoveInto(path, v+1, left.Length()-v); + left.Remove(v, 1); + } +printf("path:%s\n", path.String()); + + // user:pass@host + v = left.FindFirst("@"); + if (v > -1) { + left.MoveInto(user, 0, v); + left.Remove(0, 1); +printf("user:%s\n", user.String()); + v = user.FindFirst(":"); + if (v > -1) { + user.MoveInto(pass, v, user.Length() - v); + pass.Remove(0, 1); +printf("pass:%s\n", pass.String()); + } + } + + // host:port + v = left.FindFirst(":"); + if (v > -1) { + left.MoveInto(port, v + 1, left.Length() - v); + left.Remove(v, 1); +printf("port:%s\n", port.String()); + } + + // not much left... + host = left; +printf("host:%s\n", host.String()); + + return 0; +} + +status_t UrlWrapperApp::SplitUrl(const char *url, BString &host, BString &port, BString &user, BString &pass, BString &path) +{ + Url u(url); + if (u.InitCheck() < 0) + return u.InitCheck(); + host = u.host; + port = u.port; + user = u.user; + pass = u.pass; + path = u.path; + return 0; +} + +UrlWrapperApp::UrlWrapperApp() : BApplication(kAppSig) +{ +#if 0 + BMimeType mt(B_URL_TELNET); if (mt.InitCheck()) return; if (!mt.IsInstalled()) { mt.Install(); } +#endif #if 0 BAppFileInfo afi; if (!afi.Supports(&mt)) { @@ -46,31 +178,34 @@ TWApp::TWApp() : BApplication(app_mime) #endif } -TWApp::~TWApp() +UrlWrapperApp::~UrlWrapperApp() { } -// XXX: handle ":port" as well -status_t TWApp::SplitUrlHostUserPass(const char *url, BString &host, BString &user, BString &pass) + +status_t UrlWrapperApp::UnurlString(BString &s) { - host = url; - if (host.FindFirst("@") > -1) { - printf("%s -- %s\n", host.String(), user.String()); - host.MoveInto(user, 0, host.FindFirst("@")); - host.Remove(0, 1); - if (user.FindFirst(":") > -1) { - user.MoveInto(pass, user.FindFirst(":"), user.Length()); - pass.Remove(0, 1); - return 3; - } - printf("%s -- %s\n", host.String(), user.String()); - return 2; - } - return 1; + // TODO:WRITEME + return B_OK; } -void TWApp::ArgvReceived(int32 argc, char **argv) +status_t UrlWrapperApp::Warn(const char *url) +{ + BString message("An application has requested the system to open the following url: \n"); + message << "\n" << url << "\n\n"; + message << "This type of urls has a potential security risk.\n"; + message << "Proceed anyway ?"; + BAlert *alert = new BAlert("Warning", message.String(), "Ok", "No", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); + int32 v; + v = alert->Go(); + if (v == 0) + return B_OK; + return B_ERROR; +} + + +void UrlWrapperApp::ArgvReceived(int32 argc, char **argv) { #if 0 for (int i = 1; i < argc; i++) { @@ -80,76 +215,71 @@ void TWApp::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[] = { "/bin/sh", "-c", NULL, NULL}; + BString proto; BString host; + BString port; BString user; BString pass; + BString path; - BString url(argv[1]); + Url u(argv[1]); + BString rawurl(argv[1]); + BString url = rawurl; + if (url.FindFirst(":") < 0) { + fprintf(stderr, "malformed url: '%s'\n", url.String()); + return; + } + url.MoveInto(proto, 0, url.FindFirst(":")); + url.Remove(0, 1); + if (url.FindFirst("//") == 0) + url.RemoveFirst("//"); - // XXX: should factorize that + // pre-slice the url, but you're not forced to use the result. + // original still in rawurl. + SplitUrl(u.String(), host, port, user, pass, path); - if (url.FindFirst("telnet:") == 0) { - url.RemoveFirst("telnet:"); - if (url.FindFirst("//") == 0) - url.RemoveFirst("//"); - - - const char *failc = " || read -p 'Press any key'"; + // XXX: debug + printf("PROTO='%s'\n", proto.String()); + printf("HOST='%s'\n", host.String()); + printf("PORT='%s'\n", port.String()); + printf("USER='%s'\n", user.String()); + printf("PASS='%s'\n", pass.String()); + printf("PATH='%s'\n", path.String()); + + if (proto == "telnet") { BString cmd("telnet "); - SplitUrlHostUserPass(url.String(), host, user, pass); - printf("HOST='%s'\n", host.String()); - printf("USER='%s'\n", user.String()); - printf("PASS='%s'\n", pass.String()); if (user.Length()) cmd << "-l " << user << " "; cmd << host; printf("CMD='%s'\n", cmd.String()); cmd << failc; args[2] = (char *)cmd.String(); - be_roster->Launch(terminal_sig, 3, args); + be_roster->Launch(kTerminalSig, 3, args); return; } - if (url.FindFirst("ssh:") == 0) { - url.RemoveFirst("ssh:"); - if (url.FindFirst("//") == 0) - url.RemoveFirst("//"); - - - const char *failc = " || read -p 'Press any key'"; + if (proto == "ssh") { BString cmd("ssh "); - SplitUrlHostUserPass(url.String(), host, user, pass); - printf("HOST='%s'\n", host.String()); - printf("USER='%s'\n", user.String()); - printf("PASS='%s'\n", pass.String()); if (user.Length()) cmd << "-l " << user << " "; cmd << host; printf("CMD='%s'\n", cmd.String()); cmd << failc; args[2] = (char *)cmd.String(); - be_roster->Launch(terminal_sig, 3, args); - // XXX: handle errors + be_roster->Launch(kTerminalSig, 3, args); + // TODO: handle errors return; } - if (url.FindFirst("ftp:") == 0) { - url.RemoveFirst("ftp:"); - if (url.FindFirst("//") == 0) - url.RemoveFirst("//"); - - - const char *failc = " || read -p 'Press any key'"; + if (proto == "ftp") { BString cmd("ftp "); /* - SplitUrlHostUserPass(url.String(), host, user, pass); - printf("HOST='%s'\n", host.String()); - printf("USER='%s'\n", user.String()); - printf("PASS='%s'\n", pass.String()); if (user.Length()) cmd << "-l " << user << " "; cmd << host; @@ -158,25 +288,15 @@ void TWApp::ArgvReceived(int32 argc, char **argv) printf("CMD='%s'\n", cmd.String()); cmd << failc; args[2] = (char *)cmd.String(); - be_roster->Launch(terminal_sig, 3, args); - // XXX: handle errors + be_roster->Launch(kTerminalSig, 3, args); + // TODO: handle errors return; } - if (url.FindFirst("sftp:") == 0) { - url.RemoveFirst("sftp:"); - if (url.FindFirst("//") == 0) - url.RemoveFirst("//"); - - - const char *failc = " || read -p 'Press any key'"; + if (proto == "sftp") { BString cmd("sftp "); /* - SplitUrlHostUserPass(url.String(), host, user, pass); - printf("HOST='%s'\n", host.String()); - printf("USER='%s'\n", user.String()); - printf("PASS='%s'\n", pass.String()); if (user.Length()) cmd << "-l " << user << " "; cmd << host; @@ -185,34 +305,123 @@ void TWApp::ArgvReceived(int32 argc, char **argv) printf("CMD='%s'\n", cmd.String()); cmd << failc; args[2] = (char *)cmd.String(); - be_roster->Launch(terminal_sig, 3, args); - // XXX: handle errors + be_roster->Launch(kTerminalSig, 3, args); + // TODO: handle errors return; } + + if (proto == "finger") { + BString cmd("finger "); + + // TODO: SplitUrl thinks the user is host when it's not present... FIXME. + if (user.Length()) + cmd << user; + if (host.Length() == 0) + host = "127.0.0.1"; + cmd << "@" << host; + printf("CMD='%s'\n", cmd.String()); + cmd << pausec; + args[2] = (char *)cmd.String(); + be_roster->Launch(kTerminalSig, 3, args); + // TODO: handle errors + return; + } + +#ifdef HANDLE_FILE + if (proto == "file") { + BMessage m(B_REFS_RECEIVED); + entry_ref ref; + // UnurlString(path); + if (get_ref_for_path(path.String(), &ref) < B_OK) + return; + m.AddRef("refs", &ref); + be_roster->Launch(kTrackerSig, &m); + return; + } +#endif + +#ifdef HANDLE_SH + if (proto == "sh") { + BString cmd(url); + if (Warn(rawurl.String()) != B_OK) + return; + printf("CMD='%s'\n", cmd.String()); + cmd << pausec; + args[2] = (char *)cmd.String(); + be_roster->Launch(kTerminalSig, 3, args); + // TODO: handle errors + return; + } +#endif + +#ifdef HANDLE_BESHARE + if (proto == "beshare") { + team_id team; + be_roster->Launch(kBeShareSig, (BMessage *)NULL, &team); + BMessenger msgr(NULL, team); + if (host.Length()) { + BMessage mserver('serv'); + mserver.AddString("server", host); + //msgs.AddItem(&mserver); + msgr.SendMessage(mserver); + + } + if (path.Length()) { + BMessage mquery('quer'); + mquery.AddString("query", path); + //msgs.AddItem(&mquery); + msgr.SendMessage(mquery); + } + // TODO: handle errors + return; + } +#endif + +#ifdef HANDLE_IM + if (proto == "icq" || proto == "msn") { + // TODO + team_id team; + be_roster->Launch(kIMSig, (BMessage *)NULL, &team); + BMessenger msgr(NULL, team); + if (host.Length()) { + BMessage mserver(B_REFS_RECEIVED); + mserver.AddString("server", host); + //msgs.AddItem(&mserver); + msgr.SendMessage(mserver); + + } + // TODO: handle errors + return; + } +#endif + +#ifdef HANDLE_VLC + if (proto == "mms" || proto == "rtp" || proto == "rtsp") { + args[0] = "vlc"; + args[1] = (char *)rawurl.String(); + be_roster->Launch(kVLCSig, 2, args); + return; + } +#endif - - // finger:user@host // vnc: ? // irc: ? // - // file: -> Tracker ? // svn: ? // cvs: ? - // mms: -> VLC - // rtsp: -> VLC - // rtp: -> VLC - + // smb: ? + // nfs: ? } -void TWApp::ReadyToRun(void) +void UrlWrapperApp::ReadyToRun(void) { Quit(); } int main(int argc, char **argv) { - TWApp app; + UrlWrapperApp app; if (be_app) app.Run(); return 0; diff --git a/src/bin/urlwrapper.rdef b/src/bin/urlwrapper.rdef index 7cb440c5ea..d82c9ea128 100644 --- a/src/bin/urlwrapper.rdef +++ b/src/bin/urlwrapper.rdef @@ -1,37 +1,18 @@ - -resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.mmu_man.telnetwrapper"; +resource app_signature "application/x-vnd.haiku.urlwrapper"; +resource app_flags B_MULTIPLE_LAUNCH | B_BACKGROUND_APP | B_ARGV_ONLY; resource(1, "BEOS:FILE_TYPES") message { "types" = "application/x-vnd.Be.URL.telnet", "types" = "application/x-vnd.Be.URL.ssh", - "types" = "application/x-vnd.Be-URL.ftp" + "types" = "application/x-vnd.Be.URL.ftp", + "types" = "application/x-vnd.Be.URL.sftp", + "types" = "application/x-vnd.Be.URL.finger", + "types" = "application/x-vnd.Be.URL.sh", + "types" = "application/x-vnd.Be.URL.file", + "types" = "application/x-vnd.Be.URL.beshare", + "types" = "application/x-vnd.Be.URL.mms", + "types" = "application/x-vnd.Be.URL.rtp", + "types" = "application/x-vnd.Be.URL.rtsp" }; -resource(1, "BEOS:APP_VERSION") #'APPV' array -{ - $"0000000000000000010000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000000000000000000000000000000000000000000000000000" - $"0000000000000000" -}; - -resource(1, "BEOS:APP_FLAGS") #'APPF' $"04000000";