From 44c1a9db62546845ca4068be4756ec4697bc84ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Fri, 2 Feb 2007 16:05:56 +0000 Subject: [PATCH] Cleanup rdef Rewrote url parsing (unfinished) Added several url types. Now it handles: ftp, sftp, telnet, ssh, finger, sh, file, beshare (to BeShare), mms, rtp, rtsp (to VLC). Some make probably more sense to add to the respective apps (BeShare, VLC...) but it's still handy for now. Now please everyone go fix your apps to use generic url support instead of hardcoding http: :) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20048 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/bin/urlwrapper.cpp | 393 ++++++++++++++++++++++++++++++---------- src/bin/urlwrapper.rdef | 41 ++--- 2 files changed, 312 insertions(+), 122 deletions(-) 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";