00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ChatSession.h"
00012 #include "telnetmanager.h"
00013 #include <qstring.h>
00014 #include <qstringlist.h>
00015 #include <qregexp.h>
00016 #include <qstylesheet.h>
00017 #include <qaction.h>
00018 #include <qkeysequence.h>
00019 #include <qprocess.h>
00020 #include "mtpbrowser.h"
00021 #include <qlineedit.h>
00022 #include <qlistbox.h>
00023 #include <iostream>
00024 #include "mtpfilterssettings.h"
00025 #include "qnet.h"
00026 #include "domutil.h"
00027 #include "MtpFilter.h"
00028 #include "MtpContext.h"
00029 #include <qmessagebox.h>
00030 #include <qtextedit.h>
00031 #include <qapplication.h>
00032 #include "page.h"
00033 #include <qglobal.h>
00034
00035 ChatSession::ChatSession(const QString& session_name, QMtp * mtp, QWidget *parent, const char *name, QDomDocument * dom)
00036 : ChatPage(parent, name) {
00037
00038 host = DomUtil::readEntry(*dom,"/sessions/" + session_name + "/host","");
00039 port = DomUtil::readEntry(*dom,"/sessions/" + session_name + "/port","");
00040 this->mtp = mtp;
00041 this->m_dom = dom;
00042 this->session_name = session_name;
00043
00044
00045
00046
00047
00048
00049
00050 createTelnetManager();
00051
00052 displayStderr("Connecting to " + host + ":" + port);
00053
00054 chat_view->setTextFormat(Qt::RichText);
00055
00056 chat_view->setWrapPolicy(QTextBrowser::Anywhere);
00057 chat_view->setLinkUnderline(true);
00058
00059 item = new QStyleSheetItem(chat_view->styleSheet(),"mypre");
00060 item->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
00061
00062
00063 login_set = false;
00064 enable_stdout = true;
00065 receiving_who = false;
00066 position = 0;
00067
00068 history_up = new QAction(chat_edit,"up");
00069 history_up->setAccel(QKeySequence(SHIFT + Key_Up));
00070 history_down = new QAction(chat_edit,"down");
00071 history_down->setAccel(QKeySequence(SHIFT + Key_Down));
00072 new_line = new QAction(chat_edit,"new");
00073 new_line->setAccel(QKeySequence(CTRL + Key_Return));
00074 complete = new QAction(chat_edit,"complete");
00075 complete->setAccel(QKeySequence(Key_Tab));
00076 reconnect = new QAction(this,"reconnect");
00077 reconnect->setAccel(QKeySequence(CTRL + Key_R));
00078
00079 connect(history_up, SIGNAL(activated()),
00080 this, SLOT(slotHistoryUp()));
00081 connect(history_down, SIGNAL(activated()),
00082 this, SLOT(slotHistoryDown()));
00083 connect(new_line, SIGNAL(activated()),
00084 this, SLOT(slotNewLine()));
00085 connect(complete, SIGNAL(activated()),
00086 this, SLOT(slotComplete()));
00087 connect(reconnect, SIGNAL(activated()),
00088 this, SLOT(slotReconnect()));
00089
00090 connect(mng, SIGNAL(processExited()),
00091 this, SLOT(closeSession()));
00092
00093 connect(chat_view,SIGNAL(linkClicked(const QString &)),
00094 this, SLOT(slotLinkClicked(const QString &)));
00095
00096 connect(chat_edit, SIGNAL(returnPressed()),
00097 this, SLOT(returnPressed()));
00098
00099 chat_edit->setFocus();
00100 chat_edit->setWordWrap(QTextEdit::NoWrap);
00101 chat_edit->setTextFormat(Qt::PlainText);
00102
00103 doc_source = chat_view->source();
00104 history_iterator = 0;
00105
00106
00107 m_filter = new MtpFilter(dom,context());
00108
00109
00110 }
00111
00112
00113 ChatSession::~ChatSession() {
00114
00115 delete m_filter;
00116 for (std::vector<Page*>::iterator it = brothers.begin(); it != brothers.end(); ++it)
00117 delete (*it);
00118 }
00119
00120 void ChatSession::displayStderr(const QString& msg) {
00121 mtp->system_view->append("["+ host + ":" + port + "]" + msg);
00122 }
00123
00124 void ChatSession::displayStdout(const QString& msg) {
00125
00126 emit outputMessage(msg);
00127 QString m(msg);
00128
00129 if (m.startsWith("<Mtp> Welcome")) {
00130 this->login = m.replace(QRegExp("<Mtp> Welcome, "),"").replace(QRegExp("\\..*"),"");
00131 displayStderr("Setting user name to " + this->login + ".");
00132
00133 context()->setVar("login",caseUnsensitive(this->login));
00134 context()->setVar("Login",this->login);
00135 context()->setVar("channel","Hall");
00136
00137 QString new_m("<Mtp> Welcome, " + login + ".");
00138
00139 escape(&new_m);
00140 new_m = m_filter->filterOut(new_m);
00141 #if (QT_VERSION < 305)
00142 new_m += "<br>";
00143 #endif
00144
00145 chat_view->append(new_m);
00146
00147 position += new_m.length();
00148 login_set = true;
00149 mng->writeStdin(QString("set client ") + CLIENT);
00150 getInfo();
00151 } else if(filter(&m)) {
00152 escape(&m);
00153 m = m_filter->filterOut(m);
00154
00155
00156 QStringList list = QStringList::split("\n",m);
00157 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00158 QString mm = *it;
00159 #if (QT_VERSION < 305)
00160 mm += "<br>";
00161 #endif
00162
00163 QRegExp rx("^:(\\w+\\?" "?):(\\w+):(.*)");
00164 if (rx.exactMatch(mm)) {
00165 QString m(rx.cap(3));
00166 #if (QT_VERSION < 305)
00167 m += "<br>";
00168 #endif
00169
00170 bool ok(!(rx.cap(1).endsWith("?")));
00171 QString abbrev = ok ? rx.cap(1) : rx.cap(1).left(rx.cap(1).length()-1);
00172
00173 for (std::vector<Page*>::iterator it = brothers.begin(); it != brothers.end(); ++it)
00174 if ((*it)->name() == rx.cap(2)) {
00175
00176 (*it)->append(m);
00177
00178 ok = false;
00179 }
00180 if (ok) {
00181
00182 Page * edit = mtp->getNewPage(abbrev,rx.cap(2),this);
00183 if(edit) {
00184 brothers.push_back(edit);
00185 edit->append(m);
00186 }
00187 else
00188 displayStderr("Don't know what to do with : " + mm);
00189 }
00190 } else {
00191 chat_view->append(mm);
00192
00193 emit textDisplayed(this);
00194 }
00195 }
00196 }
00197 }
00198
00199 const QString & ChatSession::sessionName() const {
00200 return session_name;
00201 }
00202
00203 void ChatSession::kill(Page * ref) {
00204 for (std::vector<Page*>::iterator it = brothers.begin(); it != brothers.end(); ++it)
00205 if ((*it) == ref) {
00206 brothers.erase(it);
00207 return;
00208 }
00209 }
00210
00211 void ChatSession::returnPressed() {
00212
00213
00214
00215 chat_edit->doKeyboardAction(QTextEdit::ActionBackspace);
00216
00217
00218 if (login_set && (chat_edit->text() != history[0]))
00219 history.push_front(chat_edit->text());
00220
00221 QString m(chat_edit->text());
00222 send(m);
00223 chat_edit->clear();
00224
00225
00226 history_iterator = 0;
00227
00228 }
00229
00230 void ChatSession::send(const QString & m) {
00231 QString msg(m);
00232
00233 QString prefix = "";
00234
00235 QStringList l = DomUtil::readListEntry(*m_dom,"/prefixes","item");
00236 for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
00237 QRegExp re("^(" + (*it).replace(QRegExp("%l"),"[^ ]*") + ") .*");
00238 if (re.exactMatch(msg)) {
00239 prefix = re.cap(1) + " ";
00240 break;
00241 }
00242 }
00243
00244
00245 msg = msg.right(msg.length() - prefix.length());
00246
00247
00248 QStringList list = QStringList::split("\n",msg);
00249 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00250
00251
00252 QString m = *it;
00253 unsigned int limit = CHAT_BUFFER_LENGTH - prefix.length();
00254 while (m.length() > limit) {
00255 mng->writeStdin(prefix + m.left(limit));
00256 m = msg.right(m.length() - limit);
00257 }
00258 QString to_send(prefix + m);
00259 mng->writeStdin(m_filter->filterIn(to_send));
00260 }
00261
00262
00263 }
00264
00265 void ChatSession::closeSession() {
00266 QMessageBox::information(this,"Connection lost","Lost connection with host " + host);
00267 }
00268
00269 void ChatSession::slotLinkClicked(const QString & link) {
00270
00271 QStringList list = DomUtil::readListEntry(*m_dom,"/urls/available","type");
00272 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it)
00273 if(link.startsWith(*it))
00274 executeShellCommand(DomUtil::readEntry(*m_dom,QString("/urls/" + *it + "/command")).replace(QRegExp("%l"),link));
00275 }
00276
00277 void ChatSession::slotHistoryUp() {
00278
00279 if (history_iterator == 0)
00280 history_iterator=history.begin();
00281 else if (history_iterator != (--history.end()))
00282 history_iterator++;
00283 chat_edit->setText(*history_iterator);
00284 }
00285
00286 void ChatSession::slotHistoryDown() {
00287 if( history_iterator == 0)
00288 return;
00289 if (history_iterator != history.begin()) {
00290 history_iterator--;
00291 chat_edit->setText(*history_iterator);
00292 } else {
00293 chat_edit->clear();
00294 history_iterator = 0;
00295 }
00296 }
00297
00298 void ChatSession::slotNewLine() {
00299 chat_edit->doKeyboardAction(QTextEdit::ActionReturn);
00300 }
00301
00302 void ChatSession::slotComplete() {
00303 int para, index;
00304
00305 chat_edit->getCursorPosition(¶,&index);
00306 QString parag = chat_edit->text(para);
00307 QString pref;
00308
00309 if (!parag.at(index-1).isLetterOrNumber())
00310 return;
00311
00312 while (parag.at(--index).isLetterOrNumber()) {
00313 pref = parag.at(index) + pref;
00314 chat_edit->doKeyboardAction(QTextEdit::ActionBackspace);
00315 }
00316 for(uint i=0; i<users_box->count(); i++)
00317
00318 if (!(users_box->text(i).find(pref,0,false))) {
00319 if (users_box->text(i) == pref) {
00320 uint position = (i+1)%(users_box->count());
00321 chat_edit->insertAt(users_box->text(position),para,++index);
00322 chat_edit->setCursorPosition(para,index+users_box->text(position).length());
00323 } else {
00324 chat_edit->insertAt(users_box->text(i),para,++index);
00325 chat_edit->setCursorPosition(para,index+users_box->text(i).length());
00326 }
00327 return;
00328 }
00329 chat_edit->insertAt(pref,para,++index);
00330 chat_edit->setCursorPosition(para,index+pref.length());
00331 }
00332
00333 void ChatSession::slotReconnect() {
00334 delete mng;
00335 createTelnetManager();
00336 }
00337
00338 void ChatSession::escape(QString * msg) {
00339
00340 *msg = msg->replace(QRegExp("<"),"< ").replace(QRegExp(">"),"> ");
00341
00342
00343 }
00344
00345 bool ChatSession::filter(QString * msg) {
00346 if (msg->startsWith("\a")) {
00347 *msg = msg->replace(QRegExp("^\a"),"");
00348 }
00349
00350 QRegExp beep("^[0-9: ]*<Mtp> ([^ ]*) beeps you");
00351 if (beep.exactMatch(*msg))
00352 QApplication::beep();
00353
00354 QRegExp user_out("^[0-9: ]*<Mtp> ([^ ]*) (leaves|disconnects|is kicked out).*");
00355 if (user_out.exactMatch(*msg))
00356 removeUser(user_out.cap(1));
00357
00358 QRegExp user_kick("^[0-9: ]*<Mtp> You kick ([^ ]*) out.*");
00359 if (user_kick.exactMatch(*msg))
00360 removeUser(user_kick.cap(1));
00361
00362 QRegExp user_in("^[0-9: ]*<Mtp> ([^ ]*) (comes in !).*");
00363 if (user_in.exactMatch(*msg))
00364 addUser(user_in.cap(1));
00365
00366
00367
00368 if (msg->startsWith(" Login")) {
00369
00370 if (who_demanded) {
00371 receiving_who = true;
00372 displayStderr("Getting informations about connected users");
00373 who_demanded = false;
00374 enable_stdout = false;
00375 }
00376 return enable_stdout;
00377 }
00378
00379 if (msg->startsWith("-----")) {
00380 if(receiving_who)
00381 users_box->clear();
00382 return (enable_stdout);
00383 }
00384
00385 if (msg->startsWith("<Mtp> There ")) {
00386 bool tmp = this->enable_stdout;
00387 this->enable_stdout = true;
00388 this->receiving_who = false;
00389 users_box->sort();
00390 return tmp;
00391 }
00392
00393 if (receiving_who) {
00394 QString login(*msg);
00395 this->users_box->insertItem(login.replace(QRegExp(" .*"),""));
00396 return enable_stdout;
00397 }
00398
00399
00400
00401
00402 return true;
00403 }
00404
00405 void ChatSession::getInfo() {
00406 who_demanded = true;
00407 mng->writeStdin("who all");
00408 }
00409
00410 QString ChatSession::caseUnsensitive(const QString& msg) {
00411 QString up = msg.upper();
00412 QString low = msg.lower();
00413 QString res("");
00414 for (unsigned int i = 0; i<msg.length(); i++)
00415 res += "[" + up.at(i) + low.at(i) + "]";
00416 return res;
00417 }
00418
00419 void ChatSession::addUser(const QString& name) {
00420 users_box->insertItem(name);
00421 users_box->sort();
00422 }
00423
00424 void ChatSession::removeUser(const QString& name) {
00425 QListBoxItem * item = users_box->findItem(name,Qt::ExactMatch);
00426 delete item;
00427 }
00428
00429 void ChatSession::executeShellCommand(const QString& com) {
00430
00431 proc = new QProcess(this);
00432 QStringList list = QStringList::split(" ",com);
00433 proc->setArguments(list);
00434 proc->start();
00435 connect(proc, SIGNAL(processExited()),
00436 this, SLOT(deleteProcess()));
00437
00438 }
00439
00440 void ChatSession::setDomDocument(QDomDocument * dom) {
00441 m_dom = dom;
00442 }
00443
00444 void ChatSession::deleteProcess() {
00445 delete sender();
00446 }
00447
00448 void ChatSession::createTelnetManager()
00449 {
00450 mng = new TelnetManager(this);
00451 mng->setArgs(host,port);
00452 mng->setLogin(DomUtil::readEntry(*m_dom,"/sessions/" + session_name + "/login",""));
00453 mng->setPassword(DomUtil::readEntry(*m_dom,"/sessions/" + session_name + "/password",""));
00454 mng->start();
00455 }
00456
00457 QMtp* ChatSession::topLevel() const {
00458 return mtp;
00459 }
00460
00461 void ChatSession::updateFilters() {
00462 MtpFilter* f = m_filter;
00463 MtpFilter* g = new MtpFilter(m_dom,context());
00464 m_filter = g;
00465 f->setObsolete();
00466 delete f;
00467 }