]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
This is the patch as sent to me by Ricardo.
[bacula/bacula] / bacula / src / qt-console / console / console.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-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 John Walker.
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  *   Version $Id$
30  *
31  *  Console Class
32  *
33  *   Kern Sibbald, January MMVII
34  *
35  */ 
36
37 #include "bat.h"
38 #include "console.h"
39 #include "restore.h"
40 #include "select.h"
41 #include "run/run.h"
42
43 static int tls_pem_callback(char *buf, int size, const void *userdata);
44
45
46 Console::Console(QStackedWidget *parent)
47 {
48    QFont font;
49    m_parent = parent;
50    m_closeable = false;
51    m_console = this;
52
53    setupUi(this);
54    m_sock = NULL;
55    m_at_prompt = false;
56    m_at_main_prompt = false;
57    m_textEdit = textEdit;   /* our console screen */
58    m_cursor = new QTextCursor(m_textEdit->document());
59    mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
60
61    m_timer = NULL;
62    m_contextActions.append(actionStatusDir);
63    m_contextActions.append(actionConsoleHelp);
64    m_contextActions.append(actionRequestMessages);
65    m_contextActions.append(actionConsoleReload);
66    connect(actionStatusDir, SIGNAL(triggered()), this, SLOT(status_dir()));
67    connect(actionConsoleHelp, SIGNAL(triggered()), this, SLOT(consoleHelp()));
68    connect(actionConsoleReload, SIGNAL(triggered()), this, SLOT(consoleReload()));
69    connect(actionRequestMessages, SIGNAL(triggered()), this, SLOT(messages()));
70 }
71
72 Console::~Console()
73 {
74 }
75
76 void Console::startTimer()
77 {
78    m_timer = new QTimer(this);
79    QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
80    m_timer->start(mainWin->m_checkMessagesInterval*1000);
81 }
82
83 void Console::stopTimer()
84 {
85    if (m_timer) {
86       QWidget::disconnect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
87       m_timer->stop();
88       delete m_timer;
89       m_timer = NULL;
90    }
91 }
92       
93 void Console::poll_messages()
94 {
95    m_messages_pending = true;
96    if ((m_at_main_prompt) && (mainWin->m_checkMessages)){
97       write(".messages");
98       displayToPrompt();
99    }
100 }
101
102 /* Terminate any open socket */
103 void Console::terminate()
104 {
105    if (m_sock) {
106       if (m_notifier) {
107          m_notifier->setEnabled(false);
108          delete m_notifier;
109          m_notifier = NULL;
110       }
111       stopTimer();
112       m_sock->close();
113       m_sock = NULL;
114    }
115 }
116
117 /*
118  * Connect to Director. 
119  */
120 void Console::connect_dir()
121 {
122    JCR *jcr = new JCR;
123    utime_t heart_beat;
124    char buf[1024];
125    CONRES *cons;
126       
127    buf[0] = 0;
128
129    m_textEdit = textEdit;   /* our console screen */
130
131    if (!m_dir) {          
132       mainWin->set_status("No Director found.");
133       goto bail_out;
134    }
135    if (m_sock) {
136       mainWin->set_status("Already connected.");
137       goto bail_out;
138    }
139
140    memset(jcr, 0, sizeof(JCR));
141
142    mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
143    display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
144
145    /* Give GUI a chance */
146    app->processEvents();
147    
148    LockRes();
149    /* If cons==NULL, default console will be used */
150    cons = (CONRES *)GetNextRes(R_CONSOLE, NULL);
151    UnlockRes();
152
153    /* Initialize Console TLS context once */
154    if (cons && !cons->tls_ctx && (cons->tls_enable || cons->tls_require)) {
155       /* Generate passphrase prompt */
156       bsnprintf(buf, sizeof(buf), "Passphrase for Console \"%s\" TLS private key: ", 
157                 cons->name());
158
159       /* Initialize TLS context:
160        * Args: CA certfile, CA certdir, Certfile, Keyfile,
161        * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer   
162        */
163       cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
164          cons->tls_ca_certdir, cons->tls_certfile,
165          cons->tls_keyfile, tls_pem_callback, &buf, NULL, true);
166
167       if (!cons->tls_ctx) {
168          display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"),
169             m_dir->name());
170          goto bail_out;
171       }
172    }
173
174    /* Initialize Director TLS context once */
175    if (!m_dir->tls_ctx && (m_dir->tls_enable || m_dir->tls_require)) {
176       /* Generate passphrase prompt */
177       bsnprintf(buf, sizeof(buf), "Passphrase for Director \"%s\" TLS private key: ", 
178                 m_dir->name());
179
180       /* Initialize TLS context:
181        * Args: CA certfile, CA certdir, Certfile, Keyfile,
182        * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
183       m_dir->tls_ctx = new_tls_context(m_dir->tls_ca_certfile,
184                           m_dir->tls_ca_certdir, m_dir->tls_certfile,
185                           m_dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
186
187       if (!m_dir->tls_ctx) {
188          display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"),
189             m_dir->name());
190          mainWin->set_status("Connection failed");
191          goto bail_out;
192       }
193    }
194
195    if (m_dir->heartbeat_interval) {
196       heart_beat = m_dir->heartbeat_interval;
197    } else if (cons) {
198       heart_beat = cons->heartbeat_interval;
199    } else {
200       heart_beat = 0;
201    }        
202
203    m_sock = bnet_connect(NULL, 5, 15, heart_beat,
204                           _("Director daemon"), m_dir->address,
205                           NULL, m_dir->DIRport, 0);
206    if (m_sock == NULL) {
207       mainWin->set_status("Connection failed");
208       goto bail_out;
209    } else {
210       /* Update page selector to green to indicate that Console is connected */
211       mainWin->actionConnect->setIcon(QIcon(":images/connected.png"));
212       QBrush greenBrush(Qt::green);
213       QTreeWidgetItem *item = mainWin->getFromHash(this);
214       item->setForeground(0, greenBrush);
215    }
216
217    jcr->dir_bsock = m_sock;
218
219    if (!authenticate_director(jcr, m_dir, cons, buf, sizeof(buf))) {
220       display_text(buf);
221       goto bail_out;
222    }
223
224    if (buf[0]) {
225       display_text(buf);
226    }
227
228    /* Give GUI a chance */
229    app->processEvents();
230
231    mainWin->set_status(_("Initializing ..."));
232
233    /* Set up input notifier */
234    m_notifier = new QSocketNotifier(m_sock->m_fd, QSocketNotifier::Read, 0);
235    QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
236
237    write(".api 1");
238    displayToPrompt();
239
240    beginNewCommand();
241    job_list.clear();
242    client_list.clear();
243    fileset_list.clear();
244    fileset_list.clear();
245    messages_list.clear();
246    pool_list.clear();
247    storage_list.clear();
248    type_list.clear();
249    level_list.clear();
250    dir_cmd(".jobs", job_list);
251    dir_cmd(".clients", client_list);
252    dir_cmd(".filesets", fileset_list);  
253    dir_cmd(".msgs", messages_list);
254    dir_cmd(".pools", pool_list);
255    dir_cmd(".storage", storage_list);
256    dir_cmd(".types", type_list);
257    dir_cmd(".levels", level_list);
258
259    mainWin->set_status(_("Connected"));
260    startTimer();                      /* start message timer */
261
262 bail_out:
263    delete jcr;
264    return;
265 }
266
267 bool Console::dir_cmd(QString &cmd, QStringList &results)
268 {
269    return dir_cmd(cmd.toUtf8().data(), results);
270 }
271
272 /*
273  * Send a command to the Director, and return the
274  *  results in a QStringList.  
275  */
276 bool Console::dir_cmd(const char *cmd, QStringList &results)
277 {
278    int stat;
279
280    notify(false);
281    write(cmd);
282    while ((stat = read()) > 0) {
283       if (mainWin->m_displayAll) display_text(msg());
284       strip_trailing_junk(msg());
285       results << msg();
286    }
287    notify(true);
288    discardToPrompt();
289    return true;              /* ***FIXME*** return any command error */
290 }
291
292 bool Console::sql_cmd(QString &query, QStringList &results)
293 {
294    return sql_cmd(query.toUtf8().data(), results);
295 }
296
297 /*
298  * Send an sql query to the Director, and return the
299  *  results in a QStringList.  
300  */
301 bool Console::sql_cmd(const char *query, QStringList &results)
302 {
303    int stat;
304    POOL_MEM cmd(PM_MESSAGE);
305
306    if (!is_connectedGui()) {
307       return false;
308    }
309
310    notify(false);
311    
312    pm_strcpy(cmd, ".sql query=\"");
313    pm_strcat(cmd, query);
314    pm_strcat(cmd, "\"");
315    write(cmd.c_str());
316    while ((stat = read()) > 0) {
317       if (mainWin->m_displayAll) {
318          display_text(msg());
319          display_text("\n");
320       }
321       strip_trailing_junk(msg());
322       results << msg();
323    }
324    notify(true);
325    discardToPrompt();
326    return true;              /* ***FIXME*** return any command error */
327 }
328
329
330 /*  
331  * Send a job name to the director, and read all the resulting
332  *  defaults. 
333  */
334 bool Console::get_job_defaults(struct job_defaults &job_defs)
335 {
336    QString scmd;
337    int stat;
338    char *def;
339
340    notify(false);
341    beginNewCommand();
342    scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
343    write(scmd);
344    while ((stat = read()) > 0) {
345       if (mainWin->m_displayAll) display_text(msg());
346       def = strchr(msg(), '=');
347       if (!def) {
348          continue;
349       }
350       /* Pointer to default value */
351       *def++ = 0;
352       strip_trailing_junk(def);
353
354       if (strcmp(msg(), "job") == 0) {
355          if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
356             goto bail_out;
357          }
358          continue;
359       }
360       if (strcmp(msg(), "pool") == 0) {
361          job_defs.pool_name = def;
362          continue;
363       }
364       if (strcmp(msg(), "messages") == 0) {
365          job_defs.messages_name = def;
366          continue;
367       }
368       if (strcmp(msg(), "client") == 0) {
369          job_defs.client_name = def;
370          continue;
371       }
372       if (strcmp(msg(), "storage") == 0) {
373          job_defs.store_name = def;
374          continue;
375       }
376       if (strcmp(msg(), "where") == 0) {
377          job_defs.where = def;
378          continue;
379       }
380       if (strcmp(msg(), "level") == 0) {
381          job_defs.level = def;
382          continue;
383       }
384       if (strcmp(msg(), "type") == 0) {
385          job_defs.type = def;
386          continue;
387       }
388       if (strcmp(msg(), "fileset") == 0) {
389          job_defs.fileset_name = def;
390          continue;
391       }
392       if (strcmp(msg(), "catalog") == 0) {
393          job_defs.catalog_name = def;
394          continue;
395       }
396       if (strcmp(msg(), "enabled") == 0) {
397          job_defs.enabled = *def == '1' ? true : false;
398          continue;
399       }
400    }
401
402    notify(true);
403    return true;
404
405 bail_out:
406    notify(true);
407    return false;
408 }
409
410
411 /*
412  * Save user settings associated with this console
413  */
414 void Console::writeSettings()
415 {
416    QFont font = get_font();
417
418    QSettings settings(m_dir->name(), "bat");
419    settings.beginGroup("Console");
420    settings.setValue("consoleFont", font.family());
421    settings.setValue("consolePointSize", font.pointSize());
422    settings.setValue("consoleFixedPitch", font.fixedPitch());
423    settings.endGroup();
424 }
425
426 /*
427  * Read and restore user settings associated with this console
428  */
429 void Console::readSettings()
430
431    QFont font = get_font();
432
433    QSettings settings(m_dir->name(), "bat");
434    settings.beginGroup("Console");
435    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
436    font.setPointSize(settings.value("consolePointSize", 10).toInt());
437    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
438    settings.endGroup();
439    m_textEdit->setFont(font);
440 }
441
442 /*
443  * Set the console textEdit font
444  */
445 void Console::set_font()
446 {
447    bool ok;
448    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
449    if (ok) {
450       m_textEdit->setFont(font);
451    }
452 }
453
454 /*
455  * Get the console text edit font
456  */
457 const QFont Console::get_font()
458 {
459    return m_textEdit->font();
460 }
461
462 /*
463  * Slot for responding to status dir button on button bar
464  */
465 void Console::status_dir()
466 {
467    QString cmd("status dir");
468    consoleCommand(cmd);
469 }
470
471 /*
472  * Slot for responding to messages button on button bar
473  */
474 void Console::messages()
475 {
476    QString cmd(".messages");
477    consoleCommand(cmd);
478 }
479
480 /*
481  * Put text into the console window
482  */
483 void Console::display_textf(const char *fmt, ...)
484 {
485    va_list arg_ptr;
486    char buf[1000];
487    int len;
488    va_start(arg_ptr, fmt);
489    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
490    va_end(arg_ptr);
491    display_text(buf);
492 }
493
494 void Console::display_text(const QString buf)
495 {
496    m_cursor->insertText(buf);
497    update_cursor();
498 }
499
500
501 void Console::display_text(const char *buf)
502 {
503    m_cursor->insertText(buf);
504    update_cursor();
505 }
506
507 void Console::display_html(const QString buf)
508 {
509    m_cursor->insertHtml(buf);
510    update_cursor();
511 }
512
513 /* Position cursor to end of screen */
514 void Console::update_cursor()
515 {
516    QApplication::restoreOverrideCursor();
517    m_textEdit->moveCursor(QTextCursor::End);
518    m_textEdit->ensureCursorVisible();
519 }
520
521 /* 
522  * This should be moved into a bSocket class 
523  */
524 char *Console::msg()
525 {
526    if (m_sock) {
527       return m_sock->msg;
528    }
529    return NULL;
530 }
531
532 /* Send a command to the Director */
533 void Console::write_dir(const char *msg)
534 {
535    if (m_sock) {
536       mainWin->set_status(_("Processing command ..."));
537       QApplication::setOverrideCursor(Qt::WaitCursor);
538       write(msg);
539    } else {
540       mainWin->set_status(" Director not connected. Click on connect button.");
541       mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
542       QBrush redBrush(Qt::red);
543       QTreeWidgetItem *item = mainWin->getFromHash(this);
544       item->setForeground(0, redBrush);
545       m_at_prompt = false;
546       m_at_main_prompt = false;
547    }
548 }
549
550 int Console::write(const QString msg)
551 {
552    return write(msg.toUtf8().data());
553 }
554
555 int Console::write(const char *msg)
556 {
557    if (!m_sock) {
558       return -1;
559    }
560    m_sock->msglen = pm_strcpy(m_sock->msg, msg);
561    m_at_prompt = false;
562    m_at_main_prompt = false;
563    if (mainWin->m_commDebug) Pmsg1(000, "send: %s\n", msg);
564    return m_sock->send();
565
566 }
567
568 /*
569  * Get to main command prompt -- i.e. abort any subcommand
570  */
571 void Console::beginNewCommand()
572 {
573    for (int i=0; i < 3; i++) {
574       write(".");
575       while (read() > 0) {
576          if (mainWin->m_displayAll) display_text(msg());
577       }
578       if (m_at_main_prompt) {
579          break;
580       }
581    }
582    display_text("\n");
583 }
584
585 void Console::displayToPrompt()
586
587    int stat = 0;
588    if (mainWin->m_commDebug) Pmsg0(000, "DisplaytoPrompt\n");
589    while (!m_at_prompt) {
590       if ((stat=read()) > 0) {
591          display_text(msg());
592       }
593    }
594    if (mainWin->m_commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
595 }
596
597 void Console::discardToPrompt()
598
599    int stat = 0;
600    if (mainWin->m_commDebug) Pmsg0(000, "discardToPrompt\n");
601    while (!m_at_prompt) {
602       if ((stat=read()) > 0) {
603          if (mainWin->m_displayAll) display_text(msg());
604       }
605    }
606    if (mainWin->m_commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
607 }
608
609
610 /* 
611  * Blocking read from director
612  */
613 int Console::read()
614 {
615    int stat = 0;
616    while (m_sock) {
617       for (;;) {
618          stat = bnet_wait_data_intr(m_sock, 1);
619          if (stat > 0) {
620             break;
621          } 
622          app->processEvents();
623          if (m_api_set && m_messages_pending) {
624             write_dir(".messages");
625             m_messages_pending = false;
626          }
627       }
628       m_sock->msg[0] = 0;
629       stat = m_sock->recv();
630       if (stat >= 0) {
631          if (mainWin->m_commDebug) Pmsg1(000, "got: %s\n", m_sock->msg);
632          if (m_at_prompt) {
633             display_text("\n");
634             m_at_prompt = false;
635             m_at_main_prompt = false;
636          }
637       }
638       switch (m_sock->msglen) {
639       case BNET_MSGS_PENDING :
640          if (m_notifier->isEnabled()) {
641             if (mainWin->m_commDebug) Pmsg0(000, "MSGS PENDING\n");
642             write_dir(".messages");
643             displayToPrompt();
644             m_messages_pending = false;
645          }
646          m_messages_pending = true;
647          continue;
648       case BNET_CMD_OK:
649          if (mainWin->m_commDebug) Pmsg0(000, "CMD OK\n");
650          m_at_prompt = false;
651          m_at_main_prompt = false;
652          mainWin->set_status(_("Command completed ..."));
653          continue;
654       case BNET_CMD_BEGIN:
655          if (mainWin->m_commDebug) Pmsg0(000, "CMD BEGIN\n");
656          m_at_prompt = false;
657          m_at_main_prompt = false;
658          mainWin->set_status(_("Processing command ..."));
659          continue;
660       case BNET_MAIN_PROMPT:
661          if (mainWin->m_commDebug) Pmsg0(000, "MAIN PROMPT\n");
662          m_at_prompt = true;
663          m_at_main_prompt = true;
664          mainWin->set_status(_("At main prompt waiting for input ..."));
665          QApplication::restoreOverrideCursor();
666          break;
667       case BNET_PROMPT:
668          if (mainWin->m_commDebug) Pmsg0(000, "PROMPT\n");
669          m_at_prompt = true;
670          m_at_main_prompt = false;
671          mainWin->set_status(_("At prompt waiting for input ..."));
672          QApplication::restoreOverrideCursor();
673          break;
674       case BNET_CMD_FAILED:
675          if (mainWin->m_commDebug) Pmsg0(000, "CMD FAILED\n");
676          mainWin->set_status(_("Command failed."));
677          QApplication::restoreOverrideCursor();
678          break;
679       /* We should not get this one */
680       case BNET_EOD:
681          if (mainWin->m_commDebug) Pmsg0(000, "EOD\n");
682          mainWin->set_status_ready();
683          QApplication::restoreOverrideCursor();
684          if (!m_api_set) {
685             break;
686          }
687          continue;
688       case BNET_START_SELECT:
689          if (mainWin->m_commDebug) Pmsg0(000, "START SELECT\n");
690          new selectDialog(this);    
691          break;
692       case BNET_YESNO:
693          if (mainWin->m_commDebug) Pmsg0(000, "YESNO\n");
694          new yesnoPopUp(this);
695          break;
696       case BNET_RUN_CMD:
697          if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
698          new runCmdPage();
699          break;
700       case BNET_START_RTREE:
701          if (mainWin->m_commDebug) Pmsg0(000, "START RTREE CMD\n");
702          new restorePage();
703          break;
704       case BNET_END_RTREE:
705          if (mainWin->m_commDebug) Pmsg0(000, "END RTREE CMD\n");
706          break;
707       case BNET_ERROR_MSG:
708          if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
709          m_sock->recv();              /* get the message */
710          display_text(msg());
711          QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
712          break;
713       case BNET_WARNING_MSG:
714          if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
715          m_sock->recv();              /* get the message */
716          display_text(msg());
717          QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
718          break;
719       case BNET_INFO_MSG:
720          if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
721          m_sock->recv();              /* get the message */
722          display_text(msg());
723          mainWin->set_status(msg());
724          break;
725       }
726       if (is_bnet_stop(m_sock)) {         /* error or term request */
727          if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
728          stopTimer();
729          m_sock->close();
730          m_sock = NULL;
731          mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
732          QBrush redBrush(Qt::red);
733          QTreeWidgetItem *item = mainWin->getFromHash(this);
734          item->setForeground(0, redBrush);
735          m_notifier->setEnabled(false);
736          delete m_notifier;
737          m_notifier = NULL;
738          mainWin->set_status(_("Director disconnected."));
739          QApplication::restoreOverrideCursor();
740          stat = BNET_HARDEOF;
741       }
742       break;
743    } 
744    return stat;
745 }
746
747 /* Called by signal when the Director has output for us */
748 void Console::read_dir(int /* fd */)
749 {
750    if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
751    while (read() >= 0) {
752       display_text(msg());
753    }
754 }
755
756 /*
757  * When the notifier is enabled, read_dir() will automatically be
758  * called by the Qt event loop when ever there is any output 
759  * from the Directory, and read_dir() will then display it on
760  * the console.
761  *
762  * When we are in a bat dialog, we want to control *all* output
763  * from the Directory, so we set notify to off.
764  *    m_console->notifiy(false);
765  */
766 void Console::notify(bool enable) 
767
768    m_notifier->setEnabled(enable);   
769 }
770
771 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
772 {
773    m_directorTreeItem = item;
774 }
775
776 void Console::setDirRes(DIRRES *dir) 
777
778    m_dir = dir;
779 }
780
781 /*
782  * To have the ability to get the name of the director resource.
783  */
784 void Console::getDirResName(QString &name_returned)
785 {
786    name_returned = m_dir->name();
787 }
788
789 bool Console::is_connectedGui()
790 {
791    if (is_connected()) {
792       return true;
793    } else {
794       QString message("Director ");
795       message += " is currently disconnected\n  Please reconnect!!";
796       QMessageBox::warning(this, "Bat",
797          tr(message.toUtf8().data()), QMessageBox::Ok );
798       return false;
799    }
800 }
801
802 /*
803  * A temporary function to prevent connecting to the director if the director
804  * is busy with a restore.
805  */
806 bool Console::preventInUseConnect()
807 {
808    if (!is_connected()) {
809       QString message("Director ");
810       message += m_dir->name();
811       message += " is currently disconnected\n  Please reconnect!!";
812       QMessageBox::warning(this, "Bat",
813          tr(message.toUtf8().data()), QMessageBox::Ok );
814       return false;
815    } else if (!m_at_main_prompt){
816       QString message("Director ");
817       message += m_dir->name();
818       message += " is currently busy\n  Please complete restore or other "
819                  " operation !!  This is a limitation that will be resolved before a beta"
820                  " release.  This is currently an alpha release.";
821       QMessageBox::warning(this, "Bat",
822          tr(message.toUtf8().data()), QMessageBox::Ok );
823       return false;
824    } else if (!m_at_prompt){
825       QString message("Director ");
826       message += m_dir->name();
827       message += " is currently not at a prompt\n  Please try again!!";
828       QMessageBox::warning(this, "Bat",
829          tr(message.toUtf8().data()), QMessageBox::Ok );
830       return false;
831    } else {
832       return true;
833    }
834 }
835
836 /*
837  * Call-back for reading a passphrase for an encrypted PEM file
838  * This function uses getpass(), 
839  *  which uses a static buffer and is NOT thread-safe.
840  */
841 static int tls_pem_callback(char *buf, int size, const void *userdata)
842 {
843    (void)size;
844    (void)userdata;
845 #ifdef HAVE_TLS
846    const char *prompt = (const char *)userdata;
847 # if defined(HAVE_WIN32)
848    sendit(prompt);
849    if (win32_cgets(buf, size) == NULL) {
850       buf[0] = 0;
851       return 0;
852    } else {
853       return strlen(buf);
854    }
855 # else
856    char *passwd;
857
858    passwd = getpass(prompt);
859    bstrncpy(buf, passwd, size);
860    return strlen(buf);
861 # endif
862 #else
863    buf[0] = 0;
864    return 0;
865 #endif
866 }
867
868 /* Slot for responding to page selectors status help command */
869 void Console::consoleHelp()
870 {
871    QString cmd("help");
872    consoleCommand(cmd);
873 }
874
875 /* Slot for responding to page selectors reload bacula-dir.conf */
876 void Console::consoleReload()
877 {
878    QString cmd("reload");
879    consoleCommand(cmd);
880 }
881
882 /* Function to get a list of volumes */
883 void Console::getVolumeList(QStringList &volumeList)
884 {
885    QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
886    if (mainWin->m_sqlDebug) {
887       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
888    }
889    QStringList results;
890    if (sql_cmd(query, results)) {
891       QString field;
892       QStringList fieldlist;
893       /* Iterate through the lines of results. */
894       foreach (QString resultline, results) {
895          fieldlist = resultline.split("\t");
896          volumeList.append(fieldlist[0]);
897       } /* foreach resultline */
898    } /* if results from query */
899 }
900
901 /* Function to get a list of volumes */
902 void Console::getStatusList(QStringList &statusLongList)
903 {
904    QString statusQuery("SELECT JobStatusLong FROM Status");
905    if (mainWin->m_sqlDebug) {
906       Pmsg1(000, "Query cmd : %s\n",statusQuery.toUtf8().data());
907    }
908    QStringList statusResults;
909    if (sql_cmd(statusQuery, statusResults)) {
910       QString field;
911       QStringList fieldlist;
912       /* Iterate through the lines of results. */
913       foreach (QString resultline, statusResults) {
914          fieldlist = resultline.split("\t");
915          statusLongList.append(fieldlist[0]);
916       } /* foreach resultline */
917    } /* if results from statusquery */
918 }