1/* 2 * Copyright 2007-2009 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * François Revol, revol@free.fr 7 * Jonas Sundström, jonas@kirilla.com 8 */ 9 10/* 11 * CheckItOut: wraps SCM URL mime types around command line apps 12 * to check out sources in a user-friendly fashion. 13 */ 14#define DEBUG 1 15 16#include <ctype.h> 17#include <stdio.h> 18#include <unistd.h> 19 20#include <Alert.h> 21#include <Debug.h> 22#include <FilePanel.h> 23#include <NodeInfo.h> 24#include <Path.h> 25#include <Roster.h> 26#include <String.h> 27#include <Url.h> 28 29#include "checkitout.h" 30 31 32const char* kAppSig = "application/x-vnd.Haiku-checkitout"; 33const char* kTrackerSig = "application/x-vnd.Be-TRAK"; 34#if __HAIKU__ 35const char* kTerminalSig = "application/x-vnd.Haiku-Terminal"; 36#else 37const char* kTerminalSig = "application/x-vnd.Be-SHEL"; 38#endif 39 40CheckItOut::CheckItOut() : BApplication(kAppSig) 41{ 42} 43 44 45CheckItOut::~CheckItOut() 46{ 47} 48 49 50status_t 51CheckItOut::_Warn(const char* url) 52{ 53 BString message("An application has requested the system to open the " 54 "following url: \n"); 55 message << "\n" << url << "\n\n"; 56 message << "This type of URL has a potential security risk.\n"; 57 message << "Proceed anyway?"; 58 BAlert* alert = new BAlert("Warning", message.String(), "Proceed", "Stop", NULL, 59 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 60 alert->SetShortcut(1, B_ESCAPE); 61 int32 button; 62 button = alert->Go(); 63 if (button == 0) 64 return B_OK; 65 66 return B_ERROR; 67} 68 69 70status_t 71CheckItOut::_FilePanel(uint32 nodeFlavors, BString &name) 72{ 73 BFilePanel *panel = new BFilePanel(B_SAVE_PANEL); 74 /* 75 BMessenger* target = NULL, const entry_ref* directory = NULL, 76 uint32 nodeFlavors = 0, bool allowMultipleSelection = true, 77 BMessage* message = NULL, BRefFilter* refFilter = NULL, 78 bool modal = false, bool hideWhenDone = true); 79 */ 80 panel->Window()->SetTitle("Check It Out to..."); 81 panel->SetSaveText(name.String()); 82 panel->Show(); 83 return B_OK; 84} 85 86 87void 88CheckItOut::RefsReceived(BMessage* msg) 89{ 90} 91 92 93void 94CheckItOut::MessageReceived(BMessage* msg) 95{ 96 msg->PrintToStream(); 97 switch (msg->what) { 98 case B_SAVE_REQUESTED: 99 { 100 entry_ref ref; 101 BString name; 102 msg->FindRef("directory", &ref); 103 msg->FindString("name", &name); 104 _DoCheckItOut(&ref, name.String()); 105 break; 106 } 107 case B_CANCEL: 108 Quit(); 109 break; 110 } 111} 112 113 114void 115CheckItOut::ArgvReceived(int32 argc, char** argv) 116{ 117 if (argc <= 1) { 118 exit(1); 119 return; 120 } 121 122 BUrl url(argv[1]); 123 fUrlString = url; 124 125 BString full = BUrl(url).SetProtocol(BString()).UrlString(); 126 BString proto = url.Protocol(); 127 BString host = url.Host(); 128 BString port = BString() << url.Port(); 129 BString user = url.UserInfo(); 130 BString pass = url.Password(); 131 BString path = url.Path(); 132 133 if (!url.IsValid()) { 134 fprintf(stderr, "malformed url: '%s'\n", url.UrlString().String()); 135 return; 136 } 137 138 // XXX: debug 139 PRINT(("PROTO='%s'\n", proto.String())); 140 PRINT(("HOST='%s'\n", host.String())); 141 PRINT(("PORT='%s'\n", port.String())); 142 PRINT(("USER='%s'\n", user.String())); 143 PRINT(("PASS='%s'\n", pass.String())); 144 PRINT(("PATH='%s'\n", path.String())); 145 146 BString leaf(url.Path()); 147 if (leaf.FindLast('/') > -1) 148 leaf.Remove(0, leaf.FindLast('/') + 1); 149 PRINT(("leaf %s\n", leaf.String())); 150 _FilePanel(B_DIRECTORY_NODE, leaf); 151 152} 153 154status_t 155CheckItOut::_DoCheckItOut(entry_ref *ref, const char *name) 156{ 157 const char* failc = " || read -p 'Press any key'"; 158 const char* pausec = " ; read -p 'Press any key'"; 159 char* args[] = { (char *)"/bin/sh", (char *)"-c", NULL, NULL}; 160 161 BUrl url(fUrlString); 162 BString full = BUrl(url).SetProtocol(BString()).UrlString(); 163 BString proto = url.Protocol(); 164 BString host = url.Host(); 165 BString port = BString() << url.Port(); 166 BString user = url.UserInfo(); 167 BString pass = url.Password(); 168 BString path = url.Path(); 169 PRINT(("url %s\n", url.UrlString().String())); 170 BPath refPath(ref); 171 172 if (proto == "git") { 173 BString cmd("git clone "); 174 cmd << url; 175 cmd << " '" << refPath.Path() << "/" << name << "'"; 176 PRINT(("CMD='%s'\n", cmd.String())); 177 cmd << " && open '" << refPath.Path() << "/" << name << "'"; 178 cmd << failc; 179 PRINT(("CMD='%s'\n", cmd.String())); 180 args[2] = (char*)cmd.String(); 181 be_roster->Launch(kTerminalSig, 3, args); 182 return B_OK; 183 } 184 if (proto == "rsync") { 185 BString cmd("rsync "); 186 cmd << url; 187 cmd << " '" << refPath.Path() << "/" << name << "'"; 188 PRINT(("CMD='%s'\n", cmd.String())); 189 cmd << " && open '" << refPath.Path() << "/" << name << "'"; 190 cmd << failc; 191 PRINT(("CMD='%s'\n", cmd.String())); 192 args[2] = (char*)cmd.String(); 193 be_roster->Launch(kTerminalSig, 3, args); 194 return B_OK; 195 } 196 if (proto == "svn" || proto == "svn+ssh") { 197 BString cmd("svn checkout "); 198 cmd << url; 199 cmd << " '" << refPath.Path() << "/" << name << "'"; 200 PRINT(("CMD='%s'\n", cmd.String())); 201 cmd << " && open '" << refPath.Path() << "/" << name << "'"; 202 cmd << failc; 203 PRINT(("CMD='%s'\n", cmd.String())); 204 args[2] = (char*)cmd.String(); 205 be_roster->Launch(kTerminalSig, 3, args); 206 return B_OK; 207 } 208 return B_ERROR; 209} 210 211 212status_t 213CheckItOut::_DecodeUrlString(BString& string) 214{ 215 // TODO: check for %00 and bail out! 216 int32 length = string.Length(); 217 int i; 218 for (i = 0; string[i] && i < length - 2; i++) { 219 if (string[i] == '%' && isxdigit(string[i+1]) 220 && isxdigit(string[i+2])) { 221 int c; 222 sscanf(string.String() + i + 1, "%02x", &c); 223 string.Remove(i, 3); 224 string.Insert((char)c, 1, i); 225 length -= 2; 226 } 227 } 228 229 return B_OK; 230} 231 232 233void 234CheckItOut::ReadyToRun(void) 235{ 236 //Quit(); 237} 238 239 240// #pragma mark 241 242 243int main(int argc, char** argv) 244{ 245 CheckItOut app; 246 if (be_app) 247 app.Run(); 248 return 0; 249} 250 251