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