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