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