The authentication data is calculated using the hash-function mandated by the server. The HostAuth item is calculated using the HostChallenge and the hosts key. The UserAuth item is calculated using the UserChallenge and the users password. Both *Auth values are hexadecimal-encoded.<p>
-The result one single numeric item in the body that states the new session timeout in seconds (0 if the request failed). The status is "Ok" or "Unauthenticated" - in the latter case the session ID is deleted and the client needs to start with a <tt>startsession</tt> request again if it wants to retry.<p>
+The status is "Ok" or "Unauthenticated" - in the latter case the session ID is deleted and the client needs to start with a <tt>startsession</tt> request again if it wants to retry. If the request succeeds, the result body contains two numeric items (separated by a newline) that state the new session timeout and the current time as a Unix timestamp (seconds sice epoch - 1Jan1970, 00:00 UTC).<p>
A result of "Unauthenticated" can have multiple reasons: the timeout of the temporary session expired before the request was received, the authentication of the user failed, the user is not allowed to connect from this or an anonymous host, or the authentication of the host failed and the user is not allowed to connect from an anonymous host.
<table frame="1" border="1">
<tr><td>_admin</td><td>The user is an administrator and can automatically execute everything.</td></tr>
</table>
+
+
+<h2>Event Related Requests</h2>
+
+<h3>Getting a List of Events</h3>
+
+The <tt>geteventlist</tt> transaction requests all events from the server. The response is a simple XML structure that contains only very basic data for each event:<p>
+
+<pre>
+<EventList>
+ <Event id="0" start="1190543432">blechsalat</Event>
+ <Event id="1" start="1191419769">stringsalat</Event>
+</EventList>
+</pre>
+
+Each event is encapsulated in an <tt>Event</tt> tag. The events have no specific order. The <tt>id</tt> attribute contains the internal ID of the event that can be used to reference it in other requests. The <tt>start</tt> attribute contains the start time of the event as Unix timestamp. The text of the <tt>Event</tt> tag contains the title of the event.<p>
+
+<h3>Getting Detailed Event Data</h3>
+
+The <tt>geteventdata</tt> transaction returns detailed data about the event. The request body contains a space separated list of event IDs. The response looks like:<p>
+
+<pre>
+<EventData>
+ <Event id="0" start="1190543432" end="1190543532" capacity="25" defaultprice="1177" cancelled="false">
+ <Title>blechsalat</Title>
+ <Artist>Broken Blech</Artist>
+ <Description>a lot of text containing encoded &lt;b&gt;HTML&lt;/b&gt; tags</Description>
+ <Room>Invisible Library</Room>
+ <CancelReason>a damned good one</CancelReason>
+ </Event>
+ <Event id="1" start="1191419769" ...>
+ ...
+ </Event>
+</EventData>
+</pre>
+
+Attributes and tags:<br>
+<table frame="1" border="1">
+<tr><td>id</td><td>the ID of the event</td></tr>
+<tr><td>start</td><td>the start time as Unix timestamp</td></tr>
+<tr><td>end</td><td>the end time as Unix timestamp</td></tr>
+<tr><td>capacity</td><td>how many tickets may be sold for this event</td></tr>
+<tr><td>defaultprice</td><td>the default price for tickets as integer in cent (or penny or ...)</td></tr>
+<tr><td>cancelled</td><td>optional: "true" or "false" -- shows whether the event is cancelled, default is "false"</td></tr>
+<tr><td>Title</td><td>the title of the event</td></tr>
+<tr><td>Artist</td><td>the artist appearing</td></tr>
+<tr><td>Description</td><td>a description for the web page, may contain HTML</td></tr>
+<tr><td>Room</td><td>the room it is happening in (the room must exist in the list of available rooms)</td></tr>
+<tr><td>CancelReason</td><td>optional: if the event is cancelled, the reason for it (human readable)</td></tr>
+</table>
+
+If one of the requested events does not exist, it simply does not generate an <tt>Event</tt> block. It is permissible for the server to send an empty <tt>EventData</tt> tag if no data is available for the request.<p>
#include "event.h"
#include "webrequest.h"
+#include <QCoreApplication>
+#include <QDomDocument>
+#include <QDomElement>
+
MEvent::MEvent(MWebRequest*r,int id)
{
req=r;
eventid=id;
+ m_starttime=QDateTime::currentDateTime().toTime_t();
+ m_endtime=m_starttime+3600;
+ m_capacity=10;
+ m_defaultprice=100;
+ m_valid=true;
if(id>=0){
- req->request("geteventdata",QString::number(id).toAscii());
+ //get data from server
+ if(!req->request("geteventdata",QString::number(id).toAscii())){
+ m_valid=false;
+ return;
+ }
+ //check server response state
+ if(req->responseStatus()!=MWebRequest::Ok){
+ m_valid=false;
+ return;
+ }
+ //parse data
+ QDomDocument doc;
+ if(!doc.setContent(req->responseBody())){
+ m_valid=false;
+ return;
+ }
+ QDomElement root=doc.documentElement();
+ //search for this event
+ QDomNodeList nl=root.elementsByTagName("Event");
+ for(int i=0;i<nl.size();i++){
+ //filter
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ bool b;
+ int eid=el.attribute("id","x").toInt(&b);
+ if(eid!=eventid || !b)continue;
+ //get attribute data
+ m_starttime=el.attribute("start","0").toInt();
+ m_endtime=el.attribute("end","0").toInt();
+ m_capacity=el.attribute("capacity","0").toInt();
+ m_defaultprice=el.attribute("defaultprice","0").toInt();
+ bool iscancel=el.attribute("cancelled","false")=="true";
+ //get title
+ QDomNodeList nl2=el.elementsByTagName("Title");
+ if(nl2.size()>0){
+ QDomElement el2=nl2.at(0).toElement();
+ if(!el2.isNull())
+ m_title=el2.text();
+ }
+ //get artist
+ nl2=el.elementsByTagName("Artist");
+ if(nl2.size()>0){
+ QDomElement el2=nl2.at(0).toElement();
+ if(!el2.isNull())
+ m_artist=el2.text();
+ }
+ //get description
+ nl2=el.elementsByTagName("Description");
+ if(nl2.size()>0){
+ QDomElement el2=nl2.at(0).toElement();
+ if(!el2.isNull())
+ m_description=el2.text();
+ }
+ //get room
+ nl2=el.elementsByTagName("Room");
+ if(nl2.size()>0){
+ QDomElement el2=nl2.at(0).toElement();
+ if(!el2.isNull())
+ m_roomid=el2.text().trimmed();
+ }
+ //get cancel reason
+ nl2=el.elementsByTagName("CancelReason");
+ if(nl2.size()>0){
+ QDomElement el2=nl2.at(0).toElement();
+ if(!el2.isNull())
+ m_cancelreason=el2.text().trimmed();
+ }
+ if(iscancel){
+ if(m_cancelreason=="")m_cancelreason=" ";
+ }else{
+ m_cancelreason="";
+ }
+ }
}
}
{
}
-QString MEvent::title()
+QRegExp MEvent::priceRegExp()const
+{
+ return QRegExp(QCoreApplication::translate("MEvent","[0-9]+\\.[0-9]{2}","price validator regexp"));
+}
+
+QString MEvent::priceString()const
{
+ QString ret=QString::number(m_defaultprice/100);
+ ret+=QCoreApplication::translate("MEvent",".","price decimal dot");
+ ret+=QString::number((m_defaultprice/10)%10);
+ ret+=QString::number(m_defaultprice%10);
+ return ret;
}
\ No newline at end of file
void save();
- QString title();
+ QString title()const{return m_title;}
+ QString artist()const{return m_artist;}
+ QString description()const{return m_description;}
+ int startTime()const{return m_starttime;}
+ int endTime()const{return m_endtime;}
+ QString room()const{return m_roomid;}
+ int capacity()const{return m_capacity;}
+ int price()const{return m_defaultprice;}
+ bool isCancelled()const{return !m_cancelreason.isEmpty();}
+ QString cancelReason()const{return m_cancelreason.trimmed();}
+
+ QString priceString()const;
+ QRegExp priceRegExp()const;
+
+ bool isValid()const{return m_valid;}
private:
MWebRequest*req;
int eventid;
int m_defaultprice;
//if not null/empty: event has been cancelled
QString m_cancelreason;
+ //holds whether the loaded data is valid
+ bool m_valid;
};
#endif
#include "eventedit.h"
+#include <QGridLayout>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QDateTimeEdit>
+#include <QTextEdit>
+#include <QTimer>
+#include <QMessageBox>
+
MEventEditor::MEventEditor(QWidget*w,MWebRequest*r,qint32 id)
:QDialog(w),event(r,id)
{
- setWindowTitle("Event Editor");
+ if(!event.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to load event from server."));
+ //make myself disappear immediately
+ QTimer::singleShot(1,this,SLOT(reject()));
+ //no point in setting up widgets
+ return;
+ }
+ setWindowTitle(tr("Event Editor"));
req=r;
+ QGridLayout*gl;
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ QPushButton*p;
+ int lctr=0;
+ QLabel*lab;
+
+ setLayout(vl=new QVBoxLayout);
+ vl->addLayout(gl=new QGridLayout);
+
+ gl->addWidget(lab=new QLabel(tr("Title:")),lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(title=new QLineEdit,lctr,1);
+ title->setText(event.title());
+
+ gl->addWidget(lab=new QLabel(tr("Artist:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(artist=new QLineEdit,lctr,1);
+ artist->setText(event.artist());
+
+ gl->addWidget(lab=new QLabel(tr("Description:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(description=new QTextEdit,lctr,1);
+ description->setPlainText(event.description());
+
+ gl->addWidget(lab=new QLabel(tr("Start Time:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(starttime=new QDateTimeEdit,lctr,1);
+ starttime->setDisplayFormat(tr("ddd MMMM d yyyy, h:mm ap","time format"));
+ starttime->setCalendarPopup(true);
+ starttime->setDateTime(QDateTime::fromTime_t(event.startTime()));
+
+ gl->addWidget(lab=new QLabel(tr("End Time:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(endtime=new QDateTimeEdit,lctr,1);
+ endtime->setDisplayFormat(tr("ddd MMMM d yyyy, h:mm ap","time format"));
+ endtime->setCalendarPopup(true);
+ endtime->setDateTime(QDateTime::fromTime_t(event.endTime()));
+ gl->addWidget(lab=new QLabel(tr("Room/Place:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addLayout(hl=new QHBoxLayout,lctr,1);
+ hl->addWidget(room=new QLineEdit,10);
+ room->setReadOnly(true);
+ room->setText(event.room());
+ hl->addWidget(p=new QPushButton("..."),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(selectRoom()));
+
+ gl->addWidget(lab=new QLabel(tr("Capacity:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(capacity=new QSpinBox,lctr,1);
+ capacity->setRange(0,1000000000);//it is unlikely that any show will attract more people!
+ capacity->setValue(event.capacity());
+
+ gl->addWidget(lab=new QLabel(tr("Default Price:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ gl->addWidget(price=new QLineEdit,lctr,1);
+ price->setValidator(new QRegExpValidator(event.priceRegExp(),this));
+ price->setText(event.priceString());
+
+ gl->addWidget(cancelcheck=new QCheckBox(tr("Cancel Event:")),++lctr,0);
+ cancelcheck->setChecked(event.isCancelled());
+ gl->addWidget(cancelreason=new QLineEdit,lctr,1);
+ cancelreason->setEnabled(event.isCancelled());
+ cancelreason->setText(event.cancelReason());
+ connect(cancelcheck,SIGNAL(toggled(bool)),cancelreason,SLOT(setEnabled(bool)));
+
+ vl->addStretch();
+
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch();
+ hl->addWidget(p=new QPushButton(tr("Save")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ connect(p,SIGNAL(clicked()),this,SLOT(writeBack()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
}
+
+void MEventEditor::writeBack()
+{}
+
+void MEventEditor::selectRoom()
+{}
\ No newline at end of file
#include "event.h"
class MWebRequest;
+class QDateTimeEdit;
+class QLineEdit;
+class QTextEdit;
+class QCheckBox;
+class QSpinBox;
class MEventEditor:public QDialog
{
+ Q_OBJECT
public:
MEventEditor(QWidget*,MWebRequest*,qint32 id=-1);
+ private slots:
+ void writeBack();
+ void selectRoom();
private:
MWebRequest*req;
MEvent event;
+ QDateTimeEdit*starttime,*endtime;
+ QLineEdit*title,*artist,*room,*price,*cancelreason;
+ QTextEdit*description;
+ QCheckBox*cancelcheck;
+ QSpinBox*capacity;
};
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="1.1" language="de">
<context>
+ <name>MEventEditor</name>
+ <message>
+ <location filename="eventedit.cpp" line="28"/>
+ <source>Event Editor</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="38"/>
+ <source>Title:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="41"/>
+ <source>Artist:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="44"/>
+ <source>Description:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="47"/>
+ <source>Start Time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="54"/>
+ <source>ddd MMMM d yyyy, h:mm ap</source>
+ <comment>time format</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="51"/>
+ <source>End Time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="55"/>
+ <source>Room/Place:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="60"/>
+ <source>Capacity:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="63"/>
+ <source>Default Price:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="66"/>
+ <source>Cancel Event:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="72"/>
+ <source>Save</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="73"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>MKeyGen</name>
<message>
<location filename="keygen.cpp" line="86"/>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="50"/>
+ <location filename="overview.cpp" line="51"/>
<source>&Customer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="61"/>
+ <location filename="overview.cpp" line="62"/>
<source>C&onfigure</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="65"/>
+ <location filename="overview.cpp" line="66"/>
<source>Events</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="155"/>
+ <location filename="overview.cpp" line="165"/>
<source>Warning</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="155"/>
+ <location filename="overview.cpp" line="165"/>
<source>I was unable to renew the login at the server, the error was: %1</source>
<translation type="unfinished"></translation>
</message>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="46"/>
+ <location filename="overview.cpp" line="47"/>
<source>&Show details...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="47"/>
+ <location filename="overview.cpp" line="48"/>
<source>&New Event...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="48"/>
+ <location filename="overview.cpp" line="49"/>
<source>&Cancel Event...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="51"/>
+ <location filename="overview.cpp" line="52"/>
<source>&Show all customers</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="53"/>
+ <location filename="overview.cpp" line="54"/>
<source>C&art</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="54"/>
+ <location filename="overview.cpp" line="55"/>
<source>Add &Ticket</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="55"/>
+ <location filename="overview.cpp" line="56"/>
<source>Add &Voucher</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="56"/>
+ <location filename="overview.cpp" line="57"/>
<source>&Remove Item</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="57"/>
+ <location filename="overview.cpp" line="58"/>
<source>&Abort Shopping</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="59"/>
+ <location filename="overview.cpp" line="60"/>
<source>&Show all orders</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="73"/>
+ <location filename="overview.cpp" line="76"/>
<source>New Event...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="76"/>
+ <location filename="overview.cpp" line="79"/>
<source>Details...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="78"/>
+ <location filename="overview.cpp" line="83"/>
<source>Order Ticket...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="81"/>
+ <location filename="overview.cpp" line="86"/>
<source>Shopping Cart</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="90"/>
+ <location filename="overview.cpp" line="95"/>
<source>Add Ticket</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="91"/>
+ <location filename="overview.cpp" line="96"/>
<source>Add Voucher</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="92"/>
+ <location filename="overview.cpp" line="97"/>
<source>Remove Item</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="97"/>
+ <location filename="overview.cpp" line="102"/>
<source>Customer:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="102"/>
+ <location filename="overview.cpp" line="107"/>
<source>Delivery Address:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="105"/>
+ <location filename="overview.cpp" line="110"/>
<source>Comments:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="112"/>
+ <location filename="overview.cpp" line="117"/>
<source>Save Order</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="113"/>
+ <location filename="overview.cpp" line="118"/>
<source>Clear</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="123"/>
+ <location filename="overview.cpp" line="137"/>
<source>Start Time</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="123"/>
+ <location filename="overview.cpp" line="137"/>
<source>Title</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="126"/>
+ <location filename="overview.cpp" line="140"/>
<source>ddd MMMM d yyyy, h:mm ap</source>
<comment>time format</comment>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="overview.cpp" line="46"/>
+ <source>&Update Event List</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MWebRequest</name>
<!DOCTYPE TS><TS version="1.1" language="de">
<defaultcodec></defaultcodec>
<context>
+ <name>MEventEditor</name>
+ <message>
+ <location filename="eventedit.cpp" line="28"/>
+ <source>Event Editor</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="38"/>
+ <source>Title:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="41"/>
+ <source>Artist:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="44"/>
+ <source>Description:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="47"/>
+ <source>Start Time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="54"/>
+ <source>ddd MMMM d yyyy, h:mm ap</source>
+ <comment>time format</comment>
+ <translation>ddd, d.M.yyyy hh:mm</translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="51"/>
+ <source>End Time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="55"/>
+ <source>Room/Place:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="60"/>
+ <source>Capacity:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="63"/>
+ <source>Default Price:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="66"/>
+ <source>Cancel Event:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="72"/>
+ <source>Save</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="eventedit.cpp" line="73"/>
+ <source>Cancel</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>MKeyGen</name>
<message>
<location filename="keygen.cpp" line="86"/>
<translation>&Veranschdaldung</translation>
</message>
<message>
- <location filename="overview.cpp" line="50"/>
+ <location filename="overview.cpp" line="51"/>
<source>&Customer</source>
<translation>&Gunde</translation>
</message>
<message>
- <location filename="overview.cpp" line="61"/>
+ <location filename="overview.cpp" line="62"/>
<source>C&onfigure</source>
<translation>G&onfiguriern</translation>
</message>
<message>
- <location filename="overview.cpp" line="65"/>
+ <location filename="overview.cpp" line="66"/>
<source>Events</source>
<translation>Veranschdaldungen</translation>
</message>
<message>
- <location filename="overview.cpp" line="155"/>
+ <location filename="overview.cpp" line="165"/>
<source>Warning</source>
<translation>Dumm gelaufen</translation>
</message>
<message>
- <location filename="overview.cpp" line="155"/>
+ <location filename="overview.cpp" line="165"/>
<source>I was unable to renew the login at the server, the error was: %1</source>
<translation>Isch gann de' Verbindung off'n gross'n Reschner nisch erneuern. Der will nisch weil: %1</translation>
</message>
<translation>&Ohne Neds und Dobbelden Boden</translation>
</message>
<message>
- <location filename="overview.cpp" line="46"/>
+ <location filename="overview.cpp" line="47"/>
<source>&Show details...</source>
<translation>&Dedails anzeigen...</translation>
</message>
<message>
- <location filename="overview.cpp" line="47"/>
+ <location filename="overview.cpp" line="48"/>
<source>&New Event...</source>
<translation>&Neue Veranschdaldung...</translation>
</message>
<message>
- <location filename="overview.cpp" line="48"/>
+ <location filename="overview.cpp" line="49"/>
<source>&Cancel Event...</source>
<translation>Veranschdaldung &absach'n...</translation>
</message>
<message>
- <location filename="overview.cpp" line="51"/>
+ <location filename="overview.cpp" line="52"/>
<source>&Show all customers</source>
<translation>&Alle Gunden anzeigen</translation>
</message>
<message>
- <location filename="overview.cpp" line="53"/>
+ <location filename="overview.cpp" line="54"/>
<source>C&art</source>
<translation>Eing&aufswagen</translation>
</message>
<message>
- <location filename="overview.cpp" line="54"/>
+ <location filename="overview.cpp" line="55"/>
<source>Add &Ticket</source>
<translation>Ein&driddsgarde hinzufüchen</translation>
</message>
<message>
- <location filename="overview.cpp" line="55"/>
+ <location filename="overview.cpp" line="56"/>
<source>Add &Voucher</source>
<translation>&Gudschein hinzufüchen</translation>
</message>
<message>
- <location filename="overview.cpp" line="56"/>
+ <location filename="overview.cpp" line="57"/>
<source>&Remove Item</source>
<translation>Doch &ni' nehm'</translation>
</message>
<message>
- <location filename="overview.cpp" line="57"/>
+ <location filename="overview.cpp" line="58"/>
<source>&Abort Shopping</source>
<translation>&Eingauf Abbrechen</translation>
</message>
<message>
- <location filename="overview.cpp" line="59"/>
+ <location filename="overview.cpp" line="60"/>
<source>&Show all orders</source>
<translation>&Alle Beschdellungen anzeichen</translation>
</message>
<message>
- <location filename="overview.cpp" line="73"/>
+ <location filename="overview.cpp" line="76"/>
<source>New Event...</source>
<translation>Neue Veranschdaldung...</translation>
</message>
<message>
- <location filename="overview.cpp" line="76"/>
+ <location filename="overview.cpp" line="79"/>
<source>Details...</source>
<translation>Dedails anzeichen...</translation>
</message>
<message>
- <location filename="overview.cpp" line="78"/>
+ <location filename="overview.cpp" line="83"/>
<source>Order Ticket...</source>
<translation>Eindriddsgarde beschdellen...</translation>
</message>
<message>
- <location filename="overview.cpp" line="81"/>
+ <location filename="overview.cpp" line="86"/>
<source>Shopping Cart</source>
<translation>Eingaufswagen</translation>
</message>
<message>
- <location filename="overview.cpp" line="90"/>
+ <location filename="overview.cpp" line="95"/>
<source>Add Ticket</source>
<translation>Eindriddsgarde hinzufüchen</translation>
</message>
<message>
- <location filename="overview.cpp" line="91"/>
+ <location filename="overview.cpp" line="96"/>
<source>Add Voucher</source>
<translation>Gudschein hinzufüchen</translation>
</message>
<message>
- <location filename="overview.cpp" line="92"/>
+ <location filename="overview.cpp" line="97"/>
<source>Remove Item</source>
<translation>Doch ni' nehm'</translation>
</message>
<message>
- <location filename="overview.cpp" line="97"/>
+ <location filename="overview.cpp" line="102"/>
<source>Customer:</source>
<translation>Gunde:</translation>
</message>
<message>
- <location filename="overview.cpp" line="102"/>
+ <location filename="overview.cpp" line="107"/>
<source>Delivery Address:</source>
<translation>Adresse wo's Zeuch hin soll:</translation>
</message>
<message>
- <location filename="overview.cpp" line="105"/>
+ <location filename="overview.cpp" line="110"/>
<source>Comments:</source>
<translation>Wischdiches Gelaber und Gerede:</translation>
</message>
<message>
- <location filename="overview.cpp" line="112"/>
+ <location filename="overview.cpp" line="117"/>
<source>Save Order</source>
<translation>Beschdellung abschbeichern</translation>
</message>
<message>
- <location filename="overview.cpp" line="113"/>
+ <location filename="overview.cpp" line="118"/>
<source>Clear</source>
<translation>Wechwerfen und von vorne!</translation>
</message>
<message>
- <location filename="overview.cpp" line="123"/>
+ <location filename="overview.cpp" line="137"/>
<source>Start Time</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="123"/>
+ <location filename="overview.cpp" line="137"/>
<source>Title</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="overview.cpp" line="126"/>
+ <location filename="overview.cpp" line="140"/>
<source>ddd MMMM d yyyy, h:mm ap</source>
<comment>time format</comment>
<translation>ddd, d.M.yyyy hh:mm</translation>
</message>
+ <message>
+ <location filename="overview.cpp" line="46"/>
+ <source>&Update Event List</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MWebRequest</name>
webtimeout=30000;
finid=0;finerr=fin=false;
proxyport=-1;
+ sessiontimeout=0;
connect(&req,SIGNAL(requestFinished(int,bool)),this,SLOT(httpFin(int,bool)));
+ QTimer*tm=new QTimer(this);
+ tm->setSingleShot(false);
+ tm->start(10000);
+ connect(tm,SIGNAL(timeout()),this,SLOT(reloginCheck()));
}
MWebRequest::~MWebRequest(){}
//it did not finish yet, caught a timeout.
req.abort();
errstr="Web Request timed out.";
+ rspstatus="HTTP";
return false;
}
qDebug("Received Request finish for ID=%i Status=%s",finid,finerr?"Error":"Ok");
//finished with low-level error?
if(finerr){
errstr="HTTP Error: "+req.errorString();
+ rspstatus="HTTP";
qDebug("%s",errstr.toAscii().data());
return false;
}
//check for high level error
if(rsph.statusCode()!=200){
errstr="HTTP Error, return code "+QString::number(rsph.statusCode())+" "+rsph.reasonPhrase();
+ rspstatus="HTTP";
return false;
}
//get data
rspdata=req.readAll();
- rspstatus=rsph.value("x-magicsmoke-status").remove('"').trimmed();
+ rspstatus=rsph.value("x-magicsmoke-status").remove('"').trimmed().toLower();
//
qDebug("HTTP Response Headers:\n%s",rsph.toString().toAscii().data());
qDebug("HTTP Response Body:\n%s\n<-->",rspdata.data());
bool MWebRequest::doLogin()
{
+ sessiontimeout=0;
//get authentication algo
if(!request("serverinfo"))return false;
if(rspstatus.toLower()!="ok"){
errstr=tr("Unable to authenticate.");
return false;
}
- //TODO: store session timeout and do something useful with it
+ //get timestamps from server
+ QStringList tlst=QString::fromAscii(rspdata).trimmed().split("\n",QString::SkipEmptyParts);
+ qint64 tout=-1,tcur=-1;
+ bool b;
+ if(tlst.size()>=1){
+ tout=tlst[0].trimmed().toInt(&b);
+ if(!b)tout=-1;
+ }
+ if(tlst.size()>=2){
+ tcur=tlst[1].trimmed().toInt(&b);
+ if(!b)tcur=-1;
+ }
+ //correct timeout
+ if(tcur>=0){
+ int toff=QDateTime::currentDateTime().toTime_t()-tcur;
+ tout+=toff;
+ }
+ //store new timeout (don't store if this is less than 5min in the future,
+ // to prevent endless loops)
+ if((tout-300)>QDateTime::currentDateTime().toTime_t())
+ sessiontimeout=tout-30;//safety range of 20s + 10s timer delay
//all ok
return true;
}
void MWebRequest::logout()
{
+ sessiontimeout=0;
request("closesession");
}
}
return ret;
}
+
+QByteArray MWebRequest::responseBody()
+{
+ return rspdata;
+}
+
+MWebRequest::ResponseStatus MWebRequest::responseStatus()
+{
+ if(rspstatus=="HTTP")
+ return HttpError;
+ if(rspstatus=="ok")
+ return Ok;
+ if(rspstatus=="nonpost")
+ return NonPost;
+ if(rspstatus=="unauthorized")
+ return Unauthorized;
+ if(rspstatus=="notallowed")
+ return NotAllowed;
+ if(rspstatus=="invalidrequest")
+ return InvalidRequest;
+ if(rspstatus=="syntaxerror")
+ return SyntaxError;
+ return Error;
+}
+
+void MWebRequest::reloginCheck()
+{
+ if(sessiontimeout<=0)return;
+ if(sessiontimeout<=QDateTime::currentDateTime().toTime_t())
+ relogin();
+}
/**generic request method, use the macro functions if possible; this function blocks until the request either succeeds, times out or fails; returns false if the request failed or timed out*/
bool request(QString requestName,QByteArray data=QByteArray());
+ /**returns the body returned by the server for the last request*/
+ QByteArray responseBody();
+
+ enum ResponseStatus{
+ /**Everything was ok*/
+ Ok=0,
+ /**an unknown error occurred*/
+ Error=1,
+ /**the request was not a POST method (should never happen)*/
+ NonPost=2,
+ /**the session expired or was never established*/
+ Unauthorized=3,
+ /**the user does not have this right*/
+ NotAllowed=4,
+ /**the request name was invalid, the request does not exist*/
+ InvalidRequest=5,
+ /**the request data had syntactical errors*/
+ SyntaxError=6,
+ /**the HTTP transport failed or the server was unable to execute the script*/
+ HttpError=100
+ };
+
+ /**returns the (lower-case) response status of the last request*/
+ ResponseStatus responseStatus();
/**returns the last error as string*/
QString errorString();
private slots:
/**internal: used by wait loop for web requests*/
void httpFin(int,bool);
+ /**internal: check whether we need to redo the login*/
+ void reloginCheck();
signals:
/**internal: used by wait loop for web request*/
QString rspstatus;
QByteArray rspdata;
int finid,waitid;
+ //session timeout for relogin
+ qint64 sessiontimeout;
/**used by login and relogin to do the actual work*/
bool doLogin();
echo $xml->saveXml();
}
+class Event
+{
+ private $evid;
+ private $title;
+ private $artist;
+ private $description;
+ private $starttime;
+ private $endtime;
+ private $roomid;
+ private $capacity;
+ private $defaultprice;
+ private $cancelreason;
+
+ /**creates an event object, the id must be a valid eventid gotten from getAllEvents or -1 if you
+ want to create a new event*/
+ public function __construct($id)
+ {
+ global $db;
+ //check that event exists
+ $id=$id+0;
+ if($id<0)$id=-1;
+ else{
+ $res=$db->select("event","*","eventid=$id");
+ if(count($res)!=1)$id=-1;
+ else{
+ $this->title=$res[0]["title"];
+ $this->artist=$res[0]["artist"];
+ $this->description=$res[0]["description"];
+ $this->starttime=$res[0]["starttime"];
+ $this->endtime=$res[0]["endtime"];
+ $this->roomid=$res[0]["roomid"];
+ $this->capacity=$res[0]["capacity"];
+ $this->defaultprice=$res[0]["defaultprice"];
+ $this->cancelreason=$res[0]["cancelreason"];
+ }
+ }
+ //remember it
+ $this->evid=$id;
+ }
+
+ /**returns whether this event already exists in the database*/
+ public function exists()
+ {
+ return $this->evid >= 0;
+ }
+
+ /**returns the ID of the event*/
+ public function getEventId(){return $this->evid;}
+ /**returns the start time of the event*/
+ public function getStartTime(){return $this->starttime;}
+ /**returns the end time of the event*/
+ public function getEndTime(){return $this->endtime;}
+ /**returns the ticket capacity of the event*/
+ public function getCapacity(){return $this->capacity;}
+ /**returns the default price in cent of the event*/
+ public function getDefaultPrice(){return $this->defaultprice;}
+ /**returns whether the event is cancelled*/
+ public function isCancelled()
+ {
+ if($this->cancelreason===false)return false;
+ else return $this->cancelreason!="";
+ }
+ /**returns the title of the event*/
+ public function getTitle(){return $this->title;}
+ /**returns the artist of the event*/
+ public function getArtist(){return $this->artist;}
+ /**returns the room/place of the event*/
+ public function getRoomId(){return $this->roomid;}
+ /**returns the description of the event*/
+ public function getDescription(){return $this->description;}
+ /**returns the reason why the event is cancelled if isCancelled() returns true*/
+ public function getCancelReason(){return $this->cancelreason;}
+};
+
+/**machine-function: get the requested events as XML data*/
+function getEventsXml($evts)
+{
+ header("X-MagicSmoke-Status: Ok");
+ $xml=new DOMDocument;
+ $root=$xml->createElement("EventData");
+ if(count($evts)>0)
+ foreach($evts as $k => $eid){
+ $ev=new Event($eid);
+ if(!$ev->exists())continue;
+ $nod=$xml->createElement("Event");
+ $nod->setAttribute("id",$eid);
+ $nod->setAttribute("start",$ev->getStartTime());
+ $nod->setAttribute("end",$ev->getEndTime());
+ $nod->setAttribute("capacity",$ev->getCapacity());
+ $nod->setAttribute("defaultprice",$ev->getDefaultPrice());
+ $nod->setAttribute("cancelled",$ev->isCancelled()?"true":"false");
+ $nod->appendChild($xml->createElement("Title",$ev->getTitle()));
+ $nod->appendChild($xml->createElement("Artist",$ev->getArtist()));
+ $nod->appendChild($xml->createElement("Room",$ev->getRoomId()));
+ $nod->appendChild($xml->createElement("Description",$ev->getDescription()));
+ if($ev->isCancelled())
+ $nod->appendChild($xml->createElement("CancelReason",$ev->getCancelReason()));
+ $root->appendChild($nod);
+ }
+ $xml->appendChild($root);
+ echo $xml->saveXml();
+}
+
?>
\ No newline at end of file
//success
header("X-MagicSmoke-Status: Ok");
global $ClientSessionTimeout;
- $tout=time()+$ClientSessionTimeout;
+ $tout=(time()+$ClientSessionTimeout)."\n".time();
$db->update("session",array("user"=>$username,"timeout"=>$tout),"sessionid=".$db->escapeString($this->sessid));
echo $tout;
}
exit();
}
+//get a specific event
+if($SMOKEREQUEST=="geteventdata"){
+ //convert request data into array
+ $evts=array();
+ $lst=explode(" ",$REQUESTDATA);
+ foreach($lst as $k=>$v){
+ $evts[]=$v+0;
+ }
+ //get data and build XML
+ getEventsXml(array_values(array_unique($evts)));
+ exit();
+}
+
//EOF
header("X-MagicSmoke-Status: Error");
die("Internal Error: unknown command, hiccup in code structure.");