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