diff --git a/INSTALL.md b/INSTALL.md
index 6217dae8c..3458526ea 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -63,6 +63,16 @@ If compilation finishes successfully, the executable will be found as:
release/chessx
+## 4.2 Compilation of timeseal in Linux x64 systems
+
+In order to compile timeseal, to be used in Linux x64, prepare with
+
+ qmake-qt5 timeseal.pro
+
+then compile with
+
+ make
+
# 5. Problems
diff --git a/data/images/chesscom.png b/data/images/chesscom.png
deleted file mode 100644
index 5dfaf47e0..000000000
Binary files a/data/images/chesscom.png and /dev/null differ
diff --git a/data/images/chesscom_fetch.png b/data/images/chesscom_fetch.png
new file mode 100644
index 000000000..e9bc8260b
Binary files /dev/null and b/data/images/chesscom_fetch.png differ
diff --git a/data/images/fics.png b/data/images/fics.png
deleted file mode 100644
index 1c1deec65..000000000
Binary files a/data/images/fics.png and /dev/null differ
diff --git a/data/images/fics_fetch.png b/data/images/fics_fetch.png
new file mode 100644
index 000000000..c6f6bb8d3
Binary files /dev/null and b/data/images/fics_fetch.png differ
diff --git a/data/images/fics_offline.png b/data/images/fics_offline.png
new file mode 100644
index 000000000..d93462c27
Binary files /dev/null and b/data/images/fics_offline.png differ
diff --git a/data/images/fics_online.png b/data/images/fics_online.png
new file mode 100644
index 000000000..c6cf91224
Binary files /dev/null and b/data/images/fics_online.png differ
diff --git a/data/images/fics_online_timeseal.png b/data/images/fics_online_timeseal.png
new file mode 100644
index 000000000..a9a7a31f3
Binary files /dev/null and b/data/images/fics_online_timeseal.png differ
diff --git a/data/images/lichess.png b/data/images/lichess.png
deleted file mode 100644
index b53f3a2bc..000000000
Binary files a/data/images/lichess.png and /dev/null differ
diff --git a/data/images/lichess_fetch.png b/data/images/lichess_fetch.png
new file mode 100644
index 000000000..aaa260526
Binary files /dev/null and b/data/images/lichess_fetch.png differ
diff --git a/data/images/src/chesscom_fetch.svg b/data/images/src/chesscom_fetch.svg
new file mode 100644
index 000000000..6f896e96a
--- /dev/null
+++ b/data/images/src/chesscom_fetch.svg
@@ -0,0 +1,217 @@
+
+
+
+
diff --git a/data/images/src/fics_fetch.svg b/data/images/src/fics_fetch.svg
new file mode 100644
index 000000000..17e859504
--- /dev/null
+++ b/data/images/src/fics_fetch.svg
@@ -0,0 +1,206 @@
+
+
+
+
diff --git a/data/images/src/fics_offline.svg b/data/images/src/fics_offline.svg
new file mode 100644
index 000000000..71be9ca05
--- /dev/null
+++ b/data/images/src/fics_offline.svg
@@ -0,0 +1,216 @@
+
+
+
+
diff --git a/data/images/src/fics_online.svg b/data/images/src/fics_online.svg
new file mode 100644
index 000000000..b43a05db0
--- /dev/null
+++ b/data/images/src/fics_online.svg
@@ -0,0 +1,216 @@
+
+
+
+
diff --git a/data/images/src/fics_online_timeseal.svg b/data/images/src/fics_online_timeseal.svg
new file mode 100644
index 000000000..64ede425c
--- /dev/null
+++ b/data/images/src/fics_online_timeseal.svg
@@ -0,0 +1,221 @@
+
+
+
+
diff --git a/data/images/src/lichess_fetch.svg b/data/images/src/lichess_fetch.svg
new file mode 100644
index 000000000..f257c8d15
--- /dev/null
+++ b/data/images/src/lichess_fetch.svg
@@ -0,0 +1,173 @@
+
+
+
+
diff --git a/data/timeseal/unix/README.md b/data/timeseal/unix/README.md
new file mode 120000
index 000000000..2deac1e33
--- /dev/null
+++ b/data/timeseal/unix/README.md
@@ -0,0 +1 @@
+../../../src/timeseal/README.md
\ No newline at end of file
diff --git a/data/timeseal/unix/mit.md b/data/timeseal/unix/mit.md
new file mode 120000
index 000000000..a4658363a
--- /dev/null
+++ b/data/timeseal/unix/mit.md
@@ -0,0 +1 @@
+../../../src/timeseal/mit.md
\ No newline at end of file
diff --git a/data/timeseal/unix/timeseal b/data/timeseal/unix/timeseal
new file mode 120000
index 000000000..cd5490fa4
--- /dev/null
+++ b/data/timeseal/unix/timeseal
@@ -0,0 +1 @@
+../../../release/timeseal
\ No newline at end of file
diff --git a/i18n/chessx_cz.ts b/i18n/chessx_cz.ts
index dbe612a7b..3f96ce173 100644
--- a/i18n/chessx_cz.ts
+++ b/i18n/chessx_cz.ts
@@ -4311,7 +4311,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
Zkusit použít Timeseal
diff --git a/i18n/chessx_da.ts b/i18n/chessx_da.ts
index e0d923bba..9cb05ba81 100644
--- a/i18n/chessx_da.ts
+++ b/i18n/chessx_da.ts
@@ -4419,7 +4419,7 @@ Skal jeg downloade en database?
- Try to use Timeseal
+ Use timeseal
Forsøg at bruge Timeseal
diff --git a/i18n/chessx_es.ts b/i18n/chessx_es.ts
index 0e373c648..5b2674b7e 100644
--- a/i18n/chessx_es.ts
+++ b/i18n/chessx_es.ts
@@ -4410,7 +4410,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
Intente utilziar el sello de tiempo
diff --git a/i18n/chessx_fr.ts b/i18n/chessx_fr.ts
index 3d9718488..42a2227d5 100644
--- a/i18n/chessx_fr.ts
+++ b/i18n/chessx_fr.ts
@@ -4106,7 +4106,7 @@ Dois-je télécharger une base ?
- Try to use Timeseal
+ Use timeseal
Essayer d'utiliser Timeseal
diff --git a/i18n/chessx_it.ts b/i18n/chessx_it.ts
index 6bdc6ef9d..5f4a2d583 100644
--- a/i18n/chessx_it.ts
+++ b/i18n/chessx_it.ts
@@ -4347,7 +4347,7 @@ Devo caricare un database?
- Try to use Timeseal
+ Use timeseal
Teamseal was not translated.
Prova a usare Timeseal
diff --git a/i18n/chessx_nl.ts b/i18n/chessx_nl.ts
index e3845457c..7ba629ae6 100644
--- a/i18n/chessx_nl.ts
+++ b/i18n/chessx_nl.ts
@@ -4173,7 +4173,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
diff --git a/i18n/chessx_pl.ts b/i18n/chessx_pl.ts
index 2c7f91150..4285c0fb8 100644
--- a/i18n/chessx_pl.ts
+++ b/i18n/chessx_pl.ts
@@ -4553,7 +4553,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
diff --git a/i18n/chessx_pt_BR.ts b/i18n/chessx_pt_BR.ts
index 12a395abc..2862607a9 100644
--- a/i18n/chessx_pt_BR.ts
+++ b/i18n/chessx_pt_BR.ts
@@ -4081,7 +4081,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
diff --git a/i18n/chessx_ro.ts b/i18n/chessx_ro.ts
index 69a19e382..8333c2df1 100644
--- a/i18n/chessx_ro.ts
+++ b/i18n/chessx_ro.ts
@@ -4122,7 +4122,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
diff --git a/i18n/chessx_ru.ts b/i18n/chessx_ru.ts
index 3e6e9acbd..ec038ede2 100644
--- a/i18n/chessx_ru.ts
+++ b/i18n/chessx_ru.ts
@@ -4306,7 +4306,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
Попробовать использовать задержку времени
diff --git a/i18n/chessx_zh.ts b/i18n/chessx_zh.ts
index 0fc249def..84d893449 100644
--- a/i18n/chessx_zh.ts
+++ b/i18n/chessx_zh.ts
@@ -4208,7 +4208,7 @@ Shall I download a database?
- Try to use Timeseal
+ Use timeseal
diff --git a/resources.qrc b/resources.qrc
index 109157fc1..ac24508ef 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -39,7 +39,12 @@
data/images/edit_cut.png
data/images/edit_mail.png
data/images/edit_paste.png
- data/images/fics.png
+ data/images/fics_online.png
+ data/images/fics_online_timeseal.png
+ data/images/fics_offline.png
+ data/images/fics_fetch.png
+ data/images/lichess_fetch.png
+ data/images/chesscom_fetch.png
data/images/fileopen.png
data/images/filter_reset.png
data/images/filter_rev.png
@@ -77,8 +82,6 @@
data/images/insert_move.png
data/images/internet.png
data/images/button_last.png
- data/images/lichess.png
- data/images/chesscom.png
data/images/list_add.png
data/images/match.png
data/images/new_board.png
diff --git a/src/database/ficsclient.cpp b/src/database/ficsclient.cpp
index e975912e5..646a7ac8b 100644
--- a/src/database/ficsclient.cpp
+++ b/src/database/ficsclient.cpp
@@ -124,11 +124,10 @@ void FicsClient::OnReceiveTelnetMessage(QString s)
}
ProcessUnblockedMessage(s.normalized(QString::NormalizationForm_D).trimmed());
-
if (end >= 0)
- {
- m_cmd = BLKCMD_NULL;
- }
+ {
+ m_cmd = BLKCMD_NULL;
+ }
}
void FicsClient::ProcessUnblockedMessage(QString s)
@@ -138,7 +137,6 @@ void FicsClient::ProcessUnblockedMessage(QString s)
if (s.startsWith("<12>"))
{
s.remove("<12>");
- // qDebug() << s;
emit receivedBoard(m_cmd, s.trimmed());
}
else if (s.startsWith('{'))
@@ -184,11 +182,11 @@ void FicsClient::ProcessUnblockedMessage(QString s)
}
else if (m_cmd != BLKCMD_NULL)
{
- emit receivedMessage(m_cmd,s);
+ emit receivedMessage(m_cmd,s);
}
else
{
- qDebug() << "Cmd " << m_cmd << ": ignoring message: " << s;
+ qDebug() << "Cmd " << m_cmd << ": ignoring message: " << s;
}
}
}
diff --git a/src/database/settings.cpp b/src/database/settings.cpp
index 40034f1f9..911bcb01f 100644
--- a/src/database/settings.cpp
+++ b/src/database/settings.cpp
@@ -130,8 +130,8 @@ QString Settings::timesealFilePath()
#elif defined Q_OS_MAC
QString path(AppSettings->programDataPath());
return (path + QDir::separator() + "timeseal" + QDir::separator() + "mac" + QDir::separator() + "timeseal");
-#else
- return "";
+#elif defined Q_OS_UNIX
+ return (QCoreApplication::applicationDirPath() + QDir::separator() + "timeseal");
#endif
}
diff --git a/src/dialogs/preferences.ui b/src/dialogs/preferences.ui
index 420a0e484..06847fc0c 100644
--- a/src/dialogs/preferences.ui
+++ b/src/dialogs/preferences.ui
@@ -1666,7 +1666,7 @@
-
- Try to use Timeseal
+ Use timeseal
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 858399ff5..95f25daa0 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -190,6 +190,9 @@ MainWindow::MainWindow() : QMainWindow(),
connect(m_ficsConsole, SIGNAL(RequestRemoveLastMove()), this, SLOT(HandleFicsRequestRemoveMove()));
connect(m_ficsClient, SIGNAL(disconnected()), SLOT(FicsDisconnected()), Qt::QueuedConnection);
connect(m_ficsClient, SIGNAL(connected()), SLOT(FicsConnected()), Qt::QueuedConnection);
+
+
+
connect(m_ficsConsole, SIGNAL(RequestStoredMove()), SLOT(slotBoardStoredMove()));
connect(this, SIGNAL(reconfigure()), m_ficsConsole, SLOT(slotReconfigure()));
m_ficsConsole->setEnabled(false);
@@ -1137,7 +1140,18 @@ void MainWindow::openChesscom()
void MainWindow::openFICS()
{
+ //Requests a terminate connection if Fics Toggle is checked
+ if (!ficsButton->isChecked()){
+ HandleFicsCloseRequest();
+ }
+
+ //Opens Database (and connects) if Fics Toggle is unchecked
+ if (ficsButton->isChecked()){
+ // Disable the Fics toggle while connection is being stablished
+ ficsButton->setEnabled(false);
+ //Attempt etablishing a connection
openDatabaseFile(ficsPath(), false);
+ }
}
void MainWindow::copyDatabaseArchive(QString fname, QString destination)
@@ -1581,6 +1595,29 @@ void MainWindow::resizeToolBarIcons (int scale)
}
}
+/* Slot to change the pixmap of the Action for FICS connection
+To display online or offline states
+*/
+void MainWindow::FicsToggleConnected(){
+ /* Update pixmap*/
+ if (!AppSettings->getValue("/FICS/useTimeseal").toBool()){
+ ficsButton->setIcon(QIcon(":/images/fics_online.png"));
+ }
+ if (AppSettings->getValue("/FICS/useTimeseal").toBool()){
+ ficsButton->setIcon(QIcon(":/images/fics_online_timeseal.png"));
+ }
+ /* show the toggle as checked to indicate connection is online */
+ ficsButton->setChecked(true);
+ /* enable the button once again once connection is succesfully established */
+ ficsButton->setEnabled(true);
+}
+void MainWindow::FicsToggleDisconnected(){
+ /*Update pixmap */
+ ficsButton->setIcon(QIcon(":/images/fics_offline.png"));
+ /* show the toggle as not checked to indicate connection is offline */
+ ficsButton->setChecked(false);
+}
+
void MainWindow::setupActions()
{
/* File menu */
@@ -1591,11 +1628,16 @@ void MainWindow::setupActions()
file->addAction(createAction(tr("&New database..."), SLOT(slotFileNew()), Qt::CTRL + Qt::SHIFT + Qt::Key_N, fileToolBar, ":/images/new.png"));
file->addAction(createAction(tr("&Open..."), SLOT(slotFileOpen()), QKeySequence::Open, fileToolBar, ":/images/folder_open.png"));
file->addAction(createAction(tr("Open in UTF8..."), SLOT(slotFileOpenUtf8()), QKeySequence()));
- file->addAction(createAction(tr("Open FICS"), SLOT(openFICS()), QKeySequence(), fileToolBar, ":/images/fics.png"));
- file->addAction(createAction(tr("Open Lichess"), SLOT(openLichess()), QKeySequence(), fileToolBar, ":/images/lichess.png"));
- file->addAction(createAction(tr("Open chess.com"), SLOT(openChesscom()), QKeySequence(), fileToolBar, ":/images/chesscom.png"));
+ ficsButton = createAction(tr("Connect to FICS"), SLOT(openFICS()), QKeySequence(), fileToolBar, ":/images/fics_offline.png");
+ ficsButton->setCheckable(true);
+ file->addAction(ficsButton);
+ file->addAction(createAction(tr("Open Lichess"), SLOT(openLichess()), QKeySequence(), fileToolBar, ":/images/lichess_fetch.png"));
+ file->addAction(createAction(tr("Open chess.com"), SLOT(openChesscom()), QKeySequence(), fileToolBar, ":/images/chesscom_fetch.png"));
file->addAction(createAction(tr("Web Favorite"), SLOT(openWebFavorite()), QKeySequence(), fileToolBar, ":/images/folder_web.png"));
+ connect(m_ficsClient, SIGNAL(disconnected()), this, SLOT(FicsToggleDisconnected()));
+ connect(m_ficsClient, SIGNAL(connected()), this, SLOT(FicsToggleConnected()));
+
QMenu* menuRecent = file->addMenu(tr("Open recent"));
connect(menuRecent, SIGNAL( aboutToShow()), this, SLOT(updateMenuRecent()));
file->addSeparator();
diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h
index d5758a123..5d99eb5e3 100644
--- a/src/gui/mainwindow.h
+++ b/src/gui/mainwindow.h
@@ -132,11 +132,16 @@ class MainWindow: public QMainWindow
void updateLastGameList();
/* Sets size for icons in the toolbar */
QToolBar * fileToolBar, * editToolBar, * viewToolBar, * gameToolBar, * dbToolBar, * searchToolBar;
+ /* Sets the Fics button to become available class Wide */
+ QAction * ficsButton;
public slots:
/** Changes window title in response to boardview flipping**/
void updateWindowTitleFlipped(bool, bool);
/** resizes icons in the toolbar **/
void resizeToolBarIcons(int scale);
+ /** Toggle the Pixmap of FICS icon to reflect connect or disconnect status **/
+ void FicsToggleConnected();
+ void FicsToggleDisconnected();
/** Enter gaming mode */
void slotToggleGameMode();
/** Flip the board view */
diff --git a/src/timeseal/Changelog.md b/src/timeseal/Changelog.md
new file mode 100644
index 000000000..2775db258
--- /dev/null
+++ b/src/timeseal/Changelog.md
@@ -0,0 +1,4 @@
+; -*-fundamental-*-
+
+### 1.0 - 2016.02.29
+ * first release
diff --git a/src/timeseal/README.md b/src/timeseal/README.md
new file mode 100644
index 000000000..783e1e3b8
--- /dev/null
+++ b/src/timeseal/README.md
@@ -0,0 +1,26 @@
+## [zseal](https://github.com/fbergo/zseal)
+#### open source client for FICS Timeseal v2 for Linux/Unix systems
+
+:copyright: 2016 Felipe Bergo (Pulga @ FICS), fbergo at gmail_dot_com
+https://github.com/fbergo/zseal
+
+Timeseal is a protocol for network lag reporting and compensation used by the FICS chess server (freechess.org). The version 2 of the protocol provides better delay stats as the server actively pings the client periodically. FICS's FTP repository was taken down a few years ago in one of the server host changes or hard disk crashes (I forgot which) and was never put back on. Since then, there has been nowhere to download a trustable timeseal client for Linux systems.
+
+The protocol was deduced from Marcello Mamino's openseal (an implementation of timeseal v1) and the java timeseal v2 implementation in Raptor by cday
+https://github.com/Raptor-Fics-Interface/Raptor
+
+`zseal` is released under the [MIT license](mit.md); you can use this software as you please; the authors are not liable for anything the software does to you or your stuff; derived works must retain the copyright notice.
+
+#### To run from the command line
+
+`$zseal [host [port]]`
+
+- If host is omitted, the default "freechess.org" is used
+- If host is given but port is omitted, the default 5000 is used
+
+`$ zseal -v`
+or,
+`$ zseal --version`
+prints the version and exit.
+
+See: http://www.bergo.eng.br/eboard/doc.php?d=3 for further information
diff --git a/src/timeseal/config.h b/src/timeseal/config.h
new file mode 100644
index 000000000..091b41126
--- /dev/null
+++ b/src/timeseal/config.h
@@ -0,0 +1,2 @@
+#define ZSEAL_CONFIG_H 1
+#define LINUX 1
diff --git a/src/timeseal/mit.md b/src/timeseal/mit.md
new file mode 100644
index 000000000..99007ef84
--- /dev/null
+++ b/src/timeseal/mit.md
@@ -0,0 +1,26 @@
+The MIT License (MIT)
+=====================
+
+Copyright © 2016 Felipe Bergo
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the “Software”), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/src/timeseal/zseal.c b/src/timeseal/zseal.c
new file mode 100644
index 000000000..7ffce36ba
--- /dev/null
+++ b/src/timeseal/zseal.c
@@ -0,0 +1,291 @@
+/*
+ zseal - FICS Timeseal 2 client implementation
+ (C) 2016 Felipe Bergo
+ repository at https://github.com/fbergo/zseal
+
+ The MIT License (MIT)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+static int zconnect(const char *hostname,int port);
+static int zstamp(char *s,int l);
+static void zwrite(int fd,const char *buffer,int n);
+static void zreceive(int fd, char *buffer, int *rd);
+static void zsend(int fd, char *buffer, int *rd);
+static void zid(char *dest, int sz);
+static void zdie(int report);
+static void zchomp(char *s);
+static void zclean(char *s);
+
+const int BSZ = 8192;
+const char *TS_KEY = "Timestamp (FICS) v1.0 - programmed by Henrik Gram.";
+const char *VERSION = "1.0 20160229";
+
+int main(int argc, char **argv) {
+ char hostname[256], hello[512], id[256];
+ int port = 5000;
+ int fd,n;
+ fd_set fds;
+ char *buffer1=NULL, *buffer2 = NULL;
+ int bpos1=0, bpos2=0;
+
+ if (argc>=2) {
+ if (strcmp(argv[1],"-v")==0 || strcmp(argv[1],"--version")==0) {
+ fprintf(stderr,"zseal version %s (C) 2016 Felipe Bergo\n\n",VERSION);
+ return 0;
+ }
+ }
+
+ strcpy(hostname,"freechess.org");
+
+ zid(id,256);
+ snprintf(hello,511,"TIMESEAL2|%s|",id);
+
+ buffer1 = (char *) malloc(BSZ);
+ buffer2 = (char *) malloc(BSZ);
+ if (buffer1 == NULL || buffer2 == NULL) zdie(0);
+ memset(buffer1,0,BSZ);
+ memset(buffer2,0,BSZ);
+
+ if (argc >= 2) { memset(hostname,0,256); strncpy(hostname, argv[1], 255); }
+ if (argc >= 3) { port = atoi(argv[2]); }
+
+ fd = zconnect(hostname, port);
+ if (fd<0) zdie(1);
+ n = zstamp(hello,strlen(hello));
+ zwrite(fd,hello,n);
+
+ while(1) {
+ FD_ZERO(&fds);
+ FD_SET(0,&fds);
+ FD_SET(fd,&fds);
+ select(fd+1,&fds,NULL,NULL,NULL);
+
+ // stdin input
+ if(FD_ISSET(0,&fds)) {
+ bpos1 += n = read(0,buffer1+bpos1,BSZ-bpos1);
+
+ if (n==0) {
+ fprintf(stderr,"EOF from stdin\n");
+ exit(0);
+ }
+
+ if (n==-1) zdie(1);
+ zsend(fd,buffer1,&bpos1);
+
+ if (bpos1==BSZ) {
+ fprintf(stderr,"local input too long for our buffer.\n");
+ exit(1);
+ }
+ }
+
+ // network input
+ if(FD_ISSET(fd,&fds)) {
+ bpos2 += n = read(fd,buffer2,BSZ-bpos2);
+ if (!n) {
+ fprintf(stderr,"Connection closed by ICS\n");
+ exit(0);
+ }
+ if(n==-1) zdie(1);
+
+ zreceive(fd,buffer2,&bpos2);
+ if(bpos2==BSZ) {
+ fprintf(stderr,"network input too long for our buffer.\n");
+ exit(1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void zdie(int report) {
+ if (report) perror(NULL);
+ exit(1);
+}
+
+static int zconnect(const char *hostname,int port) {
+ int sockfd, res;
+ struct addrinfo *addr = NULL, hints;
+ char s_port[16];
+
+ memset(s_port,0,16);
+ snprintf(s_port,15,"%d",port);
+
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags |= AI_NUMERICSERV;
+
+ res = getaddrinfo(hostname,s_port,&hints,&addr);
+ if (res!=0) {
+ fprintf(stderr,"%s\n",gai_strerror(res));
+ exit(1);
+ }
+
+ sockfd = socket(addr->ai_family,addr->ai_socktype, addr->ai_protocol);
+ if (sockfd < 0) {
+ freeaddrinfo(addr);
+ return -1;
+ }
+
+ res = connect(sockfd, addr->ai_addr, (int) addr->ai_addrlen);
+ freeaddrinfo(addr);
+ if (res < 0) return -1;
+ return sockfd;
+}
+
+static void zwrite(int fd,const char *buffer,int n) {
+ if (write(fd,buffer,n)==-1) zdie(1);
+}
+
+static int zstamp(char *s,int l) {
+ int n;
+ struct timeval tv;
+ s[l++]=0x18;
+ gettimeofday(&tv,NULL);
+ l+=sprintf(&s[l],"%ld",(tv.tv_sec%10000)*1000+tv.tv_usec/1000);
+ s[l++]=0x19;
+ for(;l%12;l++)
+ s[l]=0x31;
+ for(n=0;n 0) {
+ memmove(buffer, buffer+i+1, (*rd));
+ i = -1;
+ }
+ }
+ }
+}
+
+static void zreceive(int fd, char *buffer, int *rd) {
+ static const char REQ[4] = { '[', 'G' , ']', 0x00 };
+ static const char ACK[2] = { 0x02, 0x39 };
+ char reply[32];
+ int i,j;
+
+ while(*rd>0) {
+ // consume and reply to all ping requests
+ for(i=0;i<=(*rd)-4;i++) {
+ if (memcmp(buffer+i,REQ,4)==0) {
+ memcpy(reply,ACK,2);
+ j=zstamp(reply,2);
+ zwrite(fd,reply,j);
+
+ (*rd) -= 4;
+ if ((*rd)-i > 0) {
+ memmove(buffer+i, buffer+i+4, (*rd)-i);
+ i--;
+ }
+ }
+ }
+ // consume line
+ for(i=0;i<*rd && buffer[i]!=0x0d;i++) ;
+ if (i<*rd) i++;
+ zwrite(1,buffer,i);
+ (*rd) -= i;
+ if (*rd > 0) memmove(buffer, buffer+i, (*rd));
+ }
+}
+
+static void zclean(char *s) {
+ unsigned int i;
+ for(i=0;i'z') s[i] = '_';
+}
+
+static void zchomp(char *s) {
+ int i;
+ i = strlen(s) - 1;
+ while(i>=0 && s[i]<32) s[i--]=0;
+}
+
+static void zid(char *dest, int sz) {
+ char user[32], uname[128], tmp[512];
+ FILE *f;
+ struct passwd *pw;
+
+ memset(user,0,32);
+ memset(uname,0,128);
+
+ pw = getpwuid(geteuid());
+ if (pw != NULL) strncpy(user,pw->pw_name,31);
+
+ f = popen("uname -a 2>&1","r");
+ if (f!=NULL) {
+ memset(tmp,0,512);
+ if (fgets(tmp, 511, f)!=NULL) {
+ zchomp(tmp);
+ snprintf(uname,127,"%s",tmp);
+ }
+ pclose(f);
+ }
+
+ zclean(user);
+ zclean(uname);
+
+ memset(dest,0,sz);
+ snprintf(dest,sz-1,"%s (zseal %s)|%s",user, VERSION, uname);
+}
diff --git a/timeseal.pro b/timeseal.pro
new file mode 100644
index 000000000..73dd85e95
--- /dev/null
+++ b/timeseal.pro
@@ -0,0 +1,37 @@
+# Main application
+DEFINES += QT_DEPRECATED_WARNINGS
+CONFIG += console
+TEMPLATE = app
+
+unix|!macx {
+ isEmpty(PREFIX) {
+ bsd {
+ PREFIX = /usr/local
+ }
+ PREFIX = /usr
+ }
+ BINDIR = $$PREFIX/bin
+
+ INSTALLS += binfiles
+
+ binfiles.files = release/timeseal
+ binfiles.path = $$BINDIR
+}
+
+HEADERS += src/timeseal/config.h
+SOURCES += src/timeseal/zseal.c
+INCLUDEPATH += src/timeseal
+
+CONFIG(debug, debug|release) {
+ DESTDIR = "debug"
+ OBJECTS_DIR = "obj_dbg"
+ DEFINES += _DEBUG
+}
+
+CONFIG(release, debug|release) {
+ DESTDIR = "release"
+ OBJECTS_DIR = "obj_rel"
+ DEFINES += QT_NO_DEBUG_OUTPUT NDEBUG
+}
+
+TARGET = timeseal