1// Sun, 18 Jun 2000
2// Y.Takagi
3
4#include <string.h>
5#include <strings.h>
6
7#include <Alert.h>
8#include <Button.h>
9#include <Directory.h>
10#include <Rect.h>
11#include <TextControl.h>
12#include <View.h>
13#include <Url.h>
14
15#include "IppContent.h"
16#include "IppURLConnection.h"
17#include "IppSetupDlg.h"
18#include "IppDefs.h"
19#include "DbgMsg.h"
20
21#define	DLG_WIDTH		350
22#define DLG_HEIGHT		80
23
24#define BUTTON_WIDTH	70
25#define BUTTON_HEIGHT	20
26
27#define URL_H			10
28#define URL_V			10
29#define URL_WIDTH		(DLG_WIDTH - URL_H - URL_H)
30#define URL_HEIGHT		20
31#define URL_TEXT		"URL"
32
33#define OK_H			(DLG_WIDTH  - BUTTON_WIDTH  - 11)
34#define OK_V			(DLG_HEIGHT - BUTTON_HEIGHT - 11)
35#define OK_TEXT			"OK"
36
37#define CANCEL_H		(OK_H - BUTTON_WIDTH - 12)
38#define CANCEL_V		OK_V
39#define CANCEL_TEXT		"Cancel"
40
41
42const BRect URL_RECT(
43	URL_H,
44	URL_V,
45	URL_H + URL_WIDTH,
46	URL_V + URL_HEIGHT);
47
48const BRect OK_RECT(
49	OK_H,
50	OK_V,
51	OK_H + BUTTON_WIDTH,
52	OK_V + BUTTON_HEIGHT);
53
54const BRect CANCEL_RECT(
55	CANCEL_H,
56	CANCEL_V,
57	CANCEL_H + BUTTON_WIDTH,
58	CANCEL_V + BUTTON_HEIGHT);
59
60enum MSGS {
61	M_CANCEL = 1,
62	M_OK
63};
64
65
66class IppSetupView : public BView {
67public:
68	IppSetupView(BRect, BDirectory *);
69	~IppSetupView() {}
70	virtual void AttachedToWindow();
71	bool UpdateViewData();
72
73private:
74	BTextControl *url;
75	BDirectory *dir;
76};
77
78IppSetupView::IppSetupView(BRect frame, BDirectory *d)
79	: BView(frame, "", B_FOLLOW_ALL, B_WILL_DRAW), dir(d)
80{
81	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
82}
83
84void IppSetupView::AttachedToWindow()
85{
86	/* url box */
87
88	url = new BTextControl(URL_RECT, "", URL_TEXT, "", NULL);
89	AddChild(url);
90	url->SetDivider(StringWidth(URL_TEXT) + 10);
91
92	/* cancel */
93
94	BButton *button = new BButton(CANCEL_RECT, "", CANCEL_TEXT, new BMessage(M_CANCEL));
95	AddChild(button);
96
97	/* ok */
98
99	button = new BButton(OK_RECT, "", OK_TEXT, new BMessage(M_OK));
100	AddChild(button);
101	button->MakeDefault(true);
102}
103
104bool IppSetupView::UpdateViewData()
105{
106	string error_msg;
107
108	if (*url->Text()) {
109		IppContent *request = new IppContent;
110		request->setOperationId(IPP_GET_PRINTER_ATTRIBUTES);
111		request->setDelimiter(IPP_OPERATION_ATTRIBUTES_TAG);
112		request->setCharset("attributes-charset", "utf-8");
113		request->setNaturalLanguage("attributes-natural-language", "en-us");
114		request->setURI("printer-uri", url->Text());
115		request->setDelimiter(IPP_END_OF_ATTRIBUTES_TAG);
116
117		IppURLConnection conn(BUrl(url->Text()));
118		conn.setIppRequest(request);
119		conn.setRequestProperty("Connection", "close");
120
121		HTTP_RESPONSECODE response_code = conn.getResponseCode();
122		if (response_code == HTTP_OK) {
123			const char *content_type = conn.getContentType();
124			if (content_type == NULL
125				|| strncasecmp(content_type, "application/ipp", 15) == 0) {
126				const IppContent *ipp_response = conn.getIppResponse();
127				if (ipp_response->good()) {
128					dir->WriteAttr(IPP_URL, B_STRING_TYPE, 0, url->Text(),
129						strlen(url->Text()) + 1);
130					return true;
131				} else {
132					error_msg = ipp_response->getStatusMessage();
133				}
134			} else {
135				error_msg = "cannot get a IPP response.";
136			}
137		} else if (response_code != HTTP_UNKNOWN) {
138			error_msg = conn.getResponseMessage();
139		} else {
140			error_msg = "cannot connect to the IPP server.";
141		}
142	} else {
143		error_msg = "please input the printer URL.";
144	}
145
146	BAlert *alert = new BAlert("", error_msg.c_str(), "OK");
147	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
148	alert->Go();
149	return false;
150}
151
152IppSetupDlg::IppSetupDlg(BDirectory *dir)
153	: BWindow(BRect(100, 100, 100 + DLG_WIDTH, 100 + DLG_HEIGHT),
154		"IPP Setup", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
155		B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE
156			| B_CLOSE_ON_ESCAPE)
157{
158	result = 0;
159
160	Lock();
161	IppSetupView *view = new IppSetupView(Bounds(), dir);
162	AddChild(view);
163	Unlock();
164
165	semaphore = create_sem(0, "IppSetupSem");
166}
167
168bool IppSetupDlg::QuitRequested()
169{
170	result = B_ERROR;
171	release_sem(semaphore);
172	return true;
173}
174
175void IppSetupDlg::MessageReceived(BMessage *msg)
176{
177	bool success;
178
179	switch (msg->what) {
180	case M_OK:
181		Lock();
182		success = ((IppSetupView *)ChildAt(0))->UpdateViewData();
183		Unlock();
184		if (success) {
185			result = B_NO_ERROR;
186			release_sem(semaphore);
187		}
188		break;
189
190	case M_CANCEL:
191		result = B_ERROR;
192		release_sem(semaphore);
193		break;
194
195	default:
196		BWindow::MessageReceived(msg);
197		break;
198	}
199}
200
201int IppSetupDlg::Go()
202{
203	Show();
204	acquire_sem(semaphore);
205	delete_sem(semaphore);
206	int value = result;
207	Lock();
208	Quit();
209	return value;
210}
211