]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/wx-console/wxbutils.cpp
Change Groupbox name to Remote Director in Configuration page if Director is not...
[bacula/bacula] / bacula / src / wx-console / wxbutils.cpp
1 /*
2  *
3  *   wxbDataParser, class that receives and analyses data
4  *
5  *    Nicolas Boichat, April-July 2004
6  *
7  *    Version $Id$
8  */
9 /*
10    Copyright (C) 2004-2006 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 /*  Windows debug builds set _DEBUG which is used by wxWidgets to select their
25  *  debug memory allocator.  Unfortunately it conflicts with Bacula's SmartAlloc.
26  * So we turn _DEBUG off since we aren't interested in things it enables.
27  */
28
29 #undef _DEBUG
30
31 #include "bacula.h"
32
33 #include "wxbutils.h"
34
35 #include "wxbmainframe.h"
36
37 #include "csprint.h"
38
39 #include "wxbtableparser.h"
40
41 /* A macro named Yield is defined under MinGW */
42 #undef Yield
43
44 bool wxbUtils::inited = false;
45
46 wxString wxbUtils::ConvertToPrintable(wxString& str) {
47    /* FIXME : Unicode support should be added to fix this problem */
48 #if (wxUSE_UNICODE == 0) && __WXGTK20__
49    wxString strnew(str);
50    /* Convert the string to something printable without unicode */
51    for (unsigned int i = 0; i < strnew.Length(); i++) {
52       /* If the character is not ASCII, print a ? */
53       if (((unsigned char)strnew[i] > (unsigned char)127)) {
54          strnew[i] = '?';
55       }
56    }
57    return strnew;
58 #else
59    return str;
60 #endif   
61 }
62
63 /* Sleeps during milliseconds (wrapper for wxUsleep (2.4) or wxMilliSleep (2.6)) */
64 void wxbUtils::MilliSleep(unsigned long milliseconds) {
65 #if wxCHECK_VERSION(2, 6, 0)
66    ::wxMilliSleep(milliseconds);
67 #else
68    ::wxUsleep(milliseconds);
69 #endif
70 }
71
72 /* Initialization */
73 void wxbUtils::Init() {
74    inited = true;
75 }
76
77 /* Reset state */
78 void wxbUtils::Reset() {
79    inited = false;
80 }
81
82 /* Parse a table in tableParser */
83 wxbTableParser* wxbUtils::CreateAndWaitForParser(wxString cmd) {
84    wxbTableParser* tableParser = new wxbTableParser();
85
86    wxbMainFrame::GetInstance()->Send(cmd);
87
88    //time_t base = wxDateTime::Now().GetTicks();
89    while (!tableParser->hasFinished()) {
90       //innerThread->Yield();
91       wxTheApp->Yield(true);
92       wxbUtils::MilliSleep(100);
93       //if (base+15 < wxDateTime::Now().GetTicks()) break;
94    }
95    return tableParser;
96 }
97
98 /* Run a command, and waits until prompt result is fully received,
99  * if keepresults is true, returns a valid pointer to a wxbPromptParser
100  * containing the data. */
101 wxbPromptParser* wxbUtils::WaitForPrompt(wxString cmd, bool keepresults) {
102    wxbPromptParser* promptParser = new wxbPromptParser();
103    
104    wxbMainFrame::GetInstance()->Send(cmd);
105     
106    //time_t base = wxDateTime::Now().GetTicks();
107    while (!promptParser->hasFinished()) {
108       //innerThread->Yield();
109       wxTheApp->Yield(true);
110       wxbUtils::MilliSleep(100);
111       //if (base+15 < wxDateTime::Now().GetTicks()) break;
112    }
113      
114    if (keepresults) {
115       return promptParser;
116    }
117    else {
118       delete promptParser;
119       return NULL;
120    }  
121 }
122
123 /* Run a command, and waits until result is fully received. */
124 wxbDataTokenizer* wxbUtils::WaitForEnd(wxString cmd, bool keepresults, bool linebyline) {
125    wxbDataTokenizer* datatokenizer = new wxbDataTokenizer(linebyline);
126
127    wxbMainFrame::GetInstance()->Send(cmd);
128    
129    //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
130    
131    //time_t base = wxDateTime::Now().GetTicks();
132    while (!datatokenizer->hasFinished()) {
133       //innerThread->Yield();
134       wxTheApp->Yield(true);
135       wxbUtils::MilliSleep(100);
136       //if (base+15 < wxDateTime::Now().GetTicks()) break;
137    }
138    
139    //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
140    
141    if (keepresults) {
142       return datatokenizer;
143    }
144    else {
145       delete datatokenizer;
146       return NULL;
147    }
148 }
149
150
151 /* Creates a new wxbDataParser, and register it in wxbMainFrame */
152 wxbDataParser::wxbDataParser(bool lineanalysis) {
153    wxbMainFrame::GetInstance()->Register(this);
154    this->lineanalysis = lineanalysis;
155 //   buffer = "";
156 }
157
158 /* Destroy a wxbDataParser, and unregister it in wxbMainFrame */
159 wxbDataParser::~wxbDataParser() {
160    wxbMainFrame::GetInstance()->Unregister(this);
161 }
162
163 /*
164  * Receives director information, forwarded by wxbMainFrame, and sends it
165  * line by line to the virtual function Analyse.
166  */
167 bool wxbDataParser::Print(wxString str, int status) {
168    bool ret = false;
169    if (lineanalysis) {
170       bool allnewline = true;
171       for (unsigned int i = 0; i < str.Length(); i++) {
172          if (!(allnewline = (str.GetChar(i) == '\n')))
173             break;
174       }
175    
176       if (allnewline) {
177          ret = Analyse(buffer << wxT("\n"), CS_DATA);
178          buffer = wxT("");
179          for (unsigned int i = 1; i < str.Length(); i++) {
180             ret = Analyse(wxT("\n"), status);
181          }
182       }
183       else {
184          wxStringTokenizer tkz(str, wxT("\n"), 
185             (wxStringTokenizerMode)(wxTOKEN_RET_DELIMS | wxTOKEN_RET_EMPTY | wxTOKEN_RET_EMPTY_ALL));
186    
187          while ( tkz.HasMoreTokens() ) {
188             buffer << tkz.GetNextToken();
189             if (buffer.Length() != 0) {
190                if ((buffer.GetChar(buffer.Length()-1) == '\n') ||
191                   (buffer.GetChar(buffer.Length()-1) == '\r')) {
192                   ret = Analyse(buffer, status);
193                   buffer = wxT("");
194                }
195             }
196          }
197       }
198    
199       if (buffer == wxT("$ ")) { // Restore console
200          ret = Analyse(buffer, status);
201          buffer = wxT("");
202       }
203    
204       if (status != CS_DATA) {
205          if (buffer.Length() != 0) {
206             ret = Analyse(buffer, CS_DATA);
207          }
208          buffer = wxT("");
209          ret = Analyse(wxT(""), status);
210       }
211    }
212    else {
213       ret = Analyse(wxString(str), status);
214    }
215    return ret;
216 }
217
218 /* Creates a new wxbDataTokenizer */
219 wxbDataTokenizer::wxbDataTokenizer(bool linebyline): wxbDataParser(linebyline), wxArrayString() {
220    finished = false;
221 }
222
223 /* Destroy a wxbDataTokenizer */
224 wxbDataTokenizer::~wxbDataTokenizer() {
225
226 }
227
228 /*
229  *   Receives director information, forwarded by wxbMainFrame.
230  */
231 bool wxbDataTokenizer::Analyse(wxString str, int status) {
232    finished = ((status == CS_END) || (status == CS_PROMPT) || (status == CS_DISCONNECTED));
233
234    if (str != wxT("")) {
235       Add(str);
236    }
237    return false;
238 }
239
240 /* Returns true if the last signal received was an end signal, 
241  * indicating that no more data is available */
242 bool wxbDataTokenizer::hasFinished() {
243    return finished;
244 }
245
246 /* Creates a new wxbDataTokenizer */
247 wxbPromptParser::wxbPromptParser(): wxbDataParser(false) {
248    finished = false;
249    prompt = false;
250    introStr = wxT("");
251    choices = NULL;
252    numerical = false;
253    questionStr = wxT("");
254 }
255
256 /* Destroy a wxbDataTokenizer */
257 wxbPromptParser::~wxbPromptParser() {
258    if (choices) {
259       delete choices;
260    }
261 }
262
263 /*
264  *   Receives director information, forwarded by wxbMainFrame.
265  */
266 bool wxbPromptParser::Analyse(wxString str, int status) {
267    if (status == CS_DATA) {
268       if (finished || prompt) { /* New question */
269          finished = false;
270          prompt = false;
271          if (choices) {
272             delete choices;
273             choices = NULL;
274             numerical = false;
275          }
276          questionStr = wxT("");
277          introStr = wxT("");
278       }
279       int i;
280       long num;
281       
282       if (((i = str.Find(wxT(": "))) > 0) && (str.Mid(0, i).Trim(false).ToLong(&num))) { /* List element */
283          if (!choices) {
284             choices = new wxArrayString();
285             choices->Add(wxT("")); /* index 0 is never used by multiple choice questions */
286             numerical = true;
287          }
288          
289          if ((long)choices->GetCount() != num) { /* new choice has begun */
290             delete choices;
291             choices = new wxArrayString();
292             choices->Add(wxT(""), num); /* fill until this number */
293             numerical = true;
294          }
295          
296          choices->Add(str.Mid(i+2).RemoveLast());
297       }
298       else if (!choices) { /* Introduction, no list received yet */
299          introStr << questionStr;
300          questionStr = wxString(str);
301       }
302       else { /* List receveived, get the question now */
303          introStr << questionStr;
304          questionStr = wxString(str);
305       }
306    }
307    else {
308       finished = ((status == CS_PROMPT) || (status == CS_END) || (status == CS_DISCONNECTED));
309       if (prompt = ((status == CS_PROMPT) && (questionStr != wxT("$ ")))) { // && (str.Find(": ") == str.Length())
310          if (introStr.Last() == '\n') {
311             introStr.RemoveLast();
312          }
313          if ((introStr != wxT("")) && (questionStr == wxT(""))) {
314             questionStr = introStr;
315             introStr = wxT("");
316          }
317          
318          if ((!choices) && (questionStr.Find(wxT("(yes/mod/no)")) > -1)) {
319             choices = new wxArrayString();
320             choices->Add(wxT("yes"));
321             choices->Add(wxT("mod"));
322             choices->Add(wxT("no"));
323             numerical = false;
324          }
325          
326          return true;
327       }
328       else { /* ended or (dis)connected */
329          if (choices) {
330             delete choices;
331             choices = NULL;
332             numerical = false;
333          }
334          questionStr = wxT("");
335          introStr = wxT("");
336       }
337    }
338    return false;
339 }
340
341 /* Returns true if the last signal received was an prompt signal, 
342  * indicating that the answer must be sent */
343 bool wxbPromptParser::hasFinished() {
344    return finished;
345 }
346
347 /* Returns true if the last message received is a prompt message */
348 bool wxbPromptParser::isPrompt() {
349    return prompt;
350 }
351
352 /* Returns multiple choice question's introduction */
353 wxString wxbPromptParser::getIntroString() {
354    return introStr;
355 }
356
357 /* Returns question string */
358 wxString wxbPromptParser::getQuestionString() {
359    return questionStr;
360 }
361
362 /* Returns a wxArrayString containing the indexed choices we have
363  * to answer the question, or NULL if this question is not a multiple
364  * choice one. */
365 wxArrayString* wxbPromptParser::getChoices() {
366    return choices;
367 }
368
369 /* Returns true if the expected answer to the choice list is a number,
370  * false if it is a string (for example yes/mod/no). */
371 bool wxbPromptParser::isNumericalChoice() {
372    return numerical;
373 }