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
This commit is contained in:
François Revol 2007-02-02 16:05:56 +00:00
parent 998579b2e1
commit 44c1a9db62
2 changed files with 312 additions and 122 deletions

View File

@ -1,3 +1,4 @@
#include <Alert.h>
#include <Application.h>
#include <AppFileInfo.h>
#include <Mime.h>
@ -8,33 +9,164 @@
#include <stdio.h>
#include <unistd.h>
#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;

View File

@ -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";