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