]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Implement Win32 bat changes made to Branch-2.4
[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 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  *   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( tr("No Director found."));
133       goto bail_out;
134    }
135    if (m_sock) {
136       mainWin->set_status( tr("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( tr("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( tr(" 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    QString buf;
589    if (mainWin->m_commDebug) Pmsg0(000, "DisplaytoPrompt\n");
590    while (!m_at_prompt) {
591       if ((stat=read()) > 0) {
592         buf += msg();
593         if (buf.size() >= 8196 || m_messages_pending) {
594            display_text(buf);
595            buf.clear();
596            m_messages_pending = false;
597         }
598       }
599    }
600    display_text(buf);
601    if (mainWin->m_commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
602 }
603
604 void Console::discardToPrompt()
605
606    int stat = 0;
607    if (mainWin->m_commDebug) Pmsg0(000, "discardToPrompt\n");
608    if (mainWin->m_displayAll) {
609       displayToPrompt();
610    } else {
611       while (!m_at_prompt) {
612          stat=read();
613       }
614    }
615    if (mainWin->m_commDebug) Pmsg1(000, "endDiscardToPrompt=%d\n", stat);
616 }
617
618 int Console::sock_read()
619 {
620    int stat;
621 #ifdef HAVE_WIN32
622    bool isEnabled = m_notifier->isEnabled();
623    if (isEnabled) {
624       m_notifier->setEnabled(false);
625    }
626    stat = m_sock->recv();
627    if (isEnabled) {
628       m_notifier->setEnabled(true);
629    }
630 #else
631    stat = m_sock->recv();
632 #endif
633    return stat;
634 }
635
636 /* 
637  * Blocking read from director
638  */
639 int Console::read()
640 {
641    int stat = 0;
642    while (m_sock) {
643       for (;;) {
644          stat = m_sock->wait_data_intr(0, 50000);
645          if (stat > 0) {
646             break;
647          } 
648          app->processEvents();
649          if (m_api_set && m_messages_pending && m_notifier->isEnabled()) {
650             write_dir(".messages");
651             m_messages_pending = false;
652          }
653       }
654       m_sock->msg[0] = 0;
655       stat = sock_read();
656       if (stat >= 0) {
657          if (mainWin->m_commDebug) Pmsg1(000, "got: %s\n", m_sock->msg);
658          if (m_at_prompt) {
659             display_text("\n");
660             m_at_prompt = false;
661             m_at_main_prompt = false;
662          }
663       }
664       switch (m_sock->msglen) {
665       case BNET_MSGS_PENDING :
666          if (m_notifier->isEnabled()) {
667             if (mainWin->m_commDebug) Pmsg0(000, "MSGS PENDING\n");
668             write_dir(".messages");
669             displayToPrompt();
670             m_messages_pending = false;
671          }
672          m_messages_pending = true;
673          continue;
674       case BNET_CMD_OK:
675          if (mainWin->m_commDebug) Pmsg0(000, "CMD OK\n");
676          m_at_prompt = false;
677          m_at_main_prompt = false;
678          mainWin->set_status(_("Command completed ..."));
679          continue;
680       case BNET_CMD_BEGIN:
681          if (mainWin->m_commDebug) Pmsg0(000, "CMD BEGIN\n");
682          m_at_prompt = false;
683          m_at_main_prompt = false;
684          mainWin->set_status(_("Processing command ..."));
685          continue;
686       case BNET_MAIN_PROMPT:
687          if (mainWin->m_commDebug) Pmsg0(000, "MAIN PROMPT\n");
688          m_at_prompt = true;
689          m_at_main_prompt = true;
690          mainWin->set_status(_("At main prompt waiting for input ..."));
691          QApplication::restoreOverrideCursor();
692          break;
693       case BNET_PROMPT:
694          if (mainWin->m_commDebug) Pmsg0(000, "PROMPT\n");
695          m_at_prompt = true;
696          m_at_main_prompt = false;
697          mainWin->set_status(_("At prompt waiting for input ..."));
698          QApplication::restoreOverrideCursor();
699          break;
700       case BNET_CMD_FAILED:
701          if (mainWin->m_commDebug) Pmsg0(000, "CMD FAILED\n");
702          mainWin->set_status(_("Command failed."));
703          QApplication::restoreOverrideCursor();
704          break;
705       /* We should not get this one */
706       case BNET_EOD:
707          if (mainWin->m_commDebug) Pmsg0(000, "EOD\n");
708          mainWin->set_status_ready();
709          QApplication::restoreOverrideCursor();
710          if (!m_api_set) {
711             break;
712          }
713          continue;
714       case BNET_START_SELECT:
715          if (mainWin->m_commDebug) Pmsg0(000, "START SELECT\n");
716          new selectDialog(this);    
717          break;
718       case BNET_YESNO:
719          if (mainWin->m_commDebug) Pmsg0(000, "YESNO\n");
720          new yesnoPopUp(this);
721          break;
722       case BNET_RUN_CMD:
723          if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
724          new runCmdPage();
725          break;
726       case BNET_START_RTREE:
727          if (mainWin->m_commDebug) Pmsg0(000, "START RTREE CMD\n");
728          new restorePage();
729          break;
730       case BNET_END_RTREE:
731          if (mainWin->m_commDebug) Pmsg0(000, "END RTREE CMD\n");
732          break;
733       case BNET_ERROR_MSG:
734          if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
735          stat = sock_read();          /* get the message */
736          display_text(msg());
737          QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
738          break;
739       case BNET_WARNING_MSG:
740          if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
741          stat = sock_read();          /* get the message */
742          display_text(msg());
743          QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
744          break;
745       case BNET_INFO_MSG:
746          if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
747          stat = sock_read();          /* get the message */
748          display_text(msg());
749          mainWin->set_status(msg());
750          break;
751       }
752       if (is_bnet_stop(m_sock)) {         /* error or term request */
753          if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
754          stopTimer();
755          m_sock->close();
756          m_sock = NULL;
757          mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
758          QBrush redBrush(Qt::red);
759          QTreeWidgetItem *item = mainWin->getFromHash(this);
760          item->setForeground(0, redBrush);
761          m_notifier->setEnabled(false);
762          delete m_notifier;
763          m_notifier = NULL;
764          mainWin->set_status(_("Director disconnected."));
765          QApplication::restoreOverrideCursor();
766          stat = BNET_HARDEOF;
767       }
768       break;
769    } 
770    return stat;
771 }
772
773 /* Called by signal when the Director has output for us */
774 void Console::read_dir(int /* fd */)
775 {
776    if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
777    while (read() >= 0) {
778       display_text(msg());
779    }
780 }
781
782 /*
783  * When the notifier is enabled, read_dir() will automatically be
784  * called by the Qt event loop when ever there is any output 
785  * from the Directory, and read_dir() will then display it on
786  * the console.
787  *
788  * When we are in a bat dialog, we want to control *all* output
789  * from the Directory, so we set notify to off.
790  *    m_console->notifiy(false);
791  */
792 void Console::notify(bool enable) 
793
794    m_notifier->setEnabled(enable);   
795 }
796
797 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
798 {
799    m_directorTreeItem = item;
800 }
801
802 void Console::setDirRes(DIRRES *dir) 
803
804    m_dir = dir;
805 }
806
807 /*
808  * To have the ability to get the name of the director resource.
809  */
810 void Console::getDirResName(QString &name_returned)
811 {
812    name_returned = m_dir->name();
813 }
814
815 bool Console::is_connectedGui()
816 {
817    if (is_connected()) {
818       return true;
819    } else {
820       QString message = tr("Director is currently disconnected\nPlease reconnect!");
821       QMessageBox::warning(this, "Bat", message, QMessageBox::Ok );
822       return false;
823    }
824 }
825
826 /*
827  * A temporary function to prevent connecting to the director if the director
828  * is busy with a restore.
829  */
830 bool Console::preventInUseConnect()
831 {
832    if (!is_connected()) {
833       QString message = tr("Director %1 is currently disconnected\n"
834                            "Please reconnect!").arg(m_dir->name());
835       QMessageBox::warning(this, "Bat", message, QMessageBox::Ok );
836       return false;
837    } else if (!m_at_main_prompt){
838       QString message = tr("Director %1 is currently busy\n  Please complete "
839                            "restore or other operation!  This is a limitation "
840                            "that will be resolved before a beta release.  "
841                            "This is currently an alpha release.").arg(m_dir->name());
842       QMessageBox::warning(this, "Bat", message, QMessageBox::Ok );
843       return false;
844    } else if (!m_at_prompt){
845       QString message = tr("Director %1 is currently not at a prompt\n"
846                            "  Please try again!").arg(m_dir->name());
847       QMessageBox::warning(this, "Bat", message, QMessageBox::Ok );
848       return false;
849    } else {
850       return true;
851    }
852 }
853
854 /*
855  * Call-back for reading a passphrase for an encrypted PEM file
856  * This function uses getpass(), 
857  *  which uses a static buffer and is NOT thread-safe.
858  */
859 static int tls_pem_callback(char *buf, int size, const void *userdata)
860 {
861    (void)size;
862    (void)userdata;
863 #ifdef HAVE_TLS
864    const char *prompt = (const char *)userdata;
865 # if defined(HAVE_WIN32)
866    //sendit(prompt);
867    if (win32_cgets(buf, size) == NULL) {
868       buf[0] = 0;
869       return 0;
870    } else {
871       return strlen(buf);
872    }
873 # else
874    char *passwd;
875
876    passwd = getpass(prompt);
877    bstrncpy(buf, passwd, size);
878    return strlen(buf);
879 # endif
880 #else
881    buf[0] = 0;
882    return 0;
883 #endif
884 }
885
886 /* Slot for responding to page selectors status help command */
887 void Console::consoleHelp()
888 {
889    QString cmd("help");
890    consoleCommand(cmd);
891 }
892
893 /* Slot for responding to page selectors reload bacula-dir.conf */
894 void Console::consoleReload()
895 {
896    QString cmd("reload");
897    consoleCommand(cmd);
898 }
899
900 /* Function to get a list of volumes */
901 void Console::getVolumeList(QStringList &volumeList)
902 {
903    QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
904    if (mainWin->m_sqlDebug) {
905       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
906    }
907    QStringList results;
908    if (sql_cmd(query, results)) {
909       QString field;
910       QStringList fieldlist;
911       /* Iterate through the lines of results. */
912       foreach (QString resultline, results) {
913          fieldlist = resultline.split("\t");
914          volumeList.append(fieldlist[0]);
915       } /* foreach resultline */
916    } /* if results from query */
917 }
918
919 /* Function to get a list of volumes */
920 void Console::getStatusList(QStringList &statusLongList)
921 {
922    QString statusQuery("SELECT JobStatusLong FROM Status");
923    if (mainWin->m_sqlDebug) {
924       Pmsg1(000, "Query cmd : %s\n",statusQuery.toUtf8().data());
925    }
926    QStringList statusResults;
927    if (sql_cmd(statusQuery, statusResults)) {
928       QString field;
929       QStringList fieldlist;
930       /* Iterate through the lines of results. */
931       foreach (QString resultline, statusResults) {
932          fieldlist = resultline.split("\t");
933          statusLongList.append(fieldlist[0]);
934       } /* foreach resultline */
935    } /* if results from statusquery */
936 }