/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set et sw=2 ts=2: */
/***************************************************************************
* praxisd.cc
*
* Tue Apr 19 09:00:29 CEST 2011
* Copyright 2011 Bent Bisballe Nyeng
* deva@aasimon.org
****************************************************************************/
/*
* This file is part of Pracro.
*
* Pracro is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Pracro is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Pracro; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "praxisd.h"
static std::string strtime(bool with_sec = true)
{
std::string ret;
time_t epoch = time(NULL);
struct tm t;
localtime_r(&epoch, &t);
char buf[32];
snprintf(buf, sizeof(buf), "%04d-%02d-%02d",
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
ret = buf;
if(with_sec) {
snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
t.tm_hour, t.tm_min, t.tm_sec);
ret += " ";
ret += buf;
}
return ret;
}
static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
std::string *str = (std::string*)userp;
str->append((char*)buffer, size * nmemb);
return size * nmemb;
}
Praxisd::Praxisd(std::string h, int port)
{
ch = curl_easy_init();
host = h;
curl_easy_setopt(ch, CURLOPT_PORT, port);
curl_easy_setopt(ch, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(ch, CURLOPT_TIMEOUT, 150L);
curl_easy_setopt(ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_easy_setopt(ch, CURLOPT_CONNECTTIMEOUT, 15L);
curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(ch, CURLOPT_USERAGENT, "libpraxisd");
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(ch, CURLOPT_FILETIME, 1L);
curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
}
Praxisd::~Praxisd()
{
curl_easy_cleanup(ch);
}
// Get Journal By CPR
std::string Praxisd::journal_get_by_cpr(std::string cpr)
{
std::string journal;
std::string uri = host + "/praxisd/1.0/journal/get_by_cpr?cpr=" + cpr;
curl_easy_setopt(ch, CURLOPT_URL, uri.c_str());
curl_easy_setopt(ch, CURLOPT_POST, 0L);
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &journal);
CURLcode errornum = curl_easy_perform(ch);
if(errornum != CURLE_OK) {
printf("Ouch %d\n", errornum);
}
time_t time;
errornum = curl_easy_getinfo(ch, CURLINFO_FILETIME, &time);
return journal;
}
time_t Praxisd::journal_last_changed(std::string cpr)
{
std::string journal;
std::string uri = host + "/praxisd/1.0/journal/get_by_cpr?cpr=" + cpr;
curl_easy_setopt(ch, CURLOPT_URL, uri.c_str());
curl_easy_setopt(ch, CURLOPT_POST, 0L);
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &journal);
CURLcode errornum = curl_easy_perform(ch);
if(errornum != CURLE_OK) {
printf("Ouch %d\n", errornum);
}
time_t time;
errornum = curl_easy_getinfo(ch, CURLINFO_FILETIME, &time);
return time;
}
void Praxisd::journal_add(std::string cpr, std::string entry)
{
std::string xml;
xml += "\n";
xml += " "+entry+"\n";
xml += "\n";
curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, (long)xml.length());
curl_easy_setopt(ch, CURLOPT_POSTFIELDS, xml.c_str());
curl_easy_setopt(ch, CURLOPT_POST, 1L);
struct curl_slist *slist = NULL;
// Unset 'Expect' header, set by CURLOPT_POSTFIELDS
slist = curl_slist_append(slist, "Expect:");
slist = curl_slist_append(slist, "Content-Type: text/xml");
slist = curl_slist_append(slist, "Connection: keep-alive");
curl_easy_setopt(ch, CURLOPT_HTTPHEADER, slist);
std::string uri = host + "/praxisd/1.0/journal/add";
curl_easy_setopt(ch, CURLOPT_URL, uri.c_str());
std::string reply;
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &reply);
CURLcode errornum = curl_easy_perform(ch);
if(errornum != CURLE_OK) {
printf("Ouch: %d %s\n", errornum, reply.c_str());
}
}
void Praxisd::add_sogeord(std::string cpr, std::string sogeord,
std::string sogetxt)
{
std::string datestr = strtime(false);
std::string xml;
xml += "\n";
xml += " \n";
xml += " "+
sogetxt+"\n";
xml += " \n";
xml += "\n";
curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, (long)xml.length());
curl_easy_setopt(ch, CURLOPT_POSTFIELDS, xml.c_str());
curl_easy_setopt(ch, CURLOPT_POST, 1L);
struct curl_slist *slist = NULL;
// Unset 'Expect' header, set by CURLOPT_POSTFIELDS
slist = curl_slist_append(slist, "Expect:");
slist = curl_slist_append(slist, "Content-Type: text/xml");
slist = curl_slist_append(slist, "Connection: keep-alive");
curl_easy_setopt(ch, CURLOPT_HTTPHEADER, slist);
std::string uri = host + "/praxisd/1.0/patient/add_sogeord";
curl_easy_setopt(ch, CURLOPT_URL, uri.c_str());
std::string reply;
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &reply);
CURLcode errornum = curl_easy_perform(ch);
if(errornum != CURLE_OK) {
printf("Ouch: %d %s\n", errornum, reply.c_str());
}
}
#define DOTAG(x) if(name == #x) str = &p.x;
#include "saxparser.h"
class PatientParser : public SAXParser {
public:
PatientParser(Praxisd::patient_t &_p) : p(_p) { str = NULL; }
void characterData(std::string &data)
{
if(str) *str += data;
}
void startTag(std::string name, std::map attr)
{
DOTAG(fornavne);
DOTAG(efternavn);
DOTAG(stilling);
DOTAG(gade);
DOTAG(by);
DOTAG(telefonnumre);
DOTAG(sikringsgr);
DOTAG(amtsnr);
DOTAG(sygekontor);
DOTAG(henvnr);
DOTAG(frilinie1);
DOTAG(frilinie2);
DOTAG(frilinie3);
DOTAG(frilinie4);
DOTAG(frilinie5);
DOTAG(ydernr);
DOTAG(created);
DOTAG(donottouch);
DOTAG(visus);
DOTAG(labkort);
DOTAG(medkort);
DOTAG(jlock);
DOTAG(unknown1);
DOTAG(henvdato);
DOTAG(aarhund);
DOTAG(fakturadato);
DOTAG(fakturabelob);
DOTAG(betaldato);
DOTAG(betalbelob);
DOTAG(jdato);
DOTAG(unknown250);
DOTAG(unknown251);
DOTAG(jtime);
if(name == "sogeords") {} // do nothing
if(name == "sogeord") {
Praxisd::sogeord_t s;
if(attr.find("sogenr") != attr.end()) s.sogenr = attr["sogenr"];
if(attr.find("sogedatpo") != attr.end()) s.sogedato = attr["sogedato"];
p.sogeord.push_back(s);
str = &p.sogeord[p.sogeord.size() - 1].sogetxt;
}
}
void endTag(std::string name)
{
str = NULL;
}
private:
std::string *str;
Praxisd::patient_t &p;
};
Praxisd::patient_t Praxisd::patient_get_by_cpr(std::string cpr)
{
patient_t p;
std::string xml;
std::string uri = host + "/praxisd/1.0/patient/get_by_cpr?cpr=" + cpr;
curl_easy_setopt(ch, CURLOPT_URL, uri.c_str());
curl_easy_setopt(ch, CURLOPT_POST, 0L);
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &xml);
CURLcode errornum = curl_easy_perform(ch);
if(errornum != CURLE_OK) {
printf("Ouch %d\n", errornum);
}
PatientParser parser(p);
parser.parse(xml.data(), xml.length());
return p;
}
#ifdef TEST_PRAXISD
//deps: saxparser.cc debug.cc log.cc
//cflags: $(CURL_CFLAGS) $(EXPAT_CFLAGS) -I..
//libs: $(CURL_LIBS) $(EXPAT_LIBS)
#include "test.h"
#define NL "\r\n"
#define CPR "1505050505"
TEST_BEGIN;
Praxisd p("http://localhost", 10000);
std::string j = p.journal_get_by_cpr(CPR);
TEST_NOTEQUAL(j, "", "Did we get a journal?");
std::string more = "less is more... much much more.";
p.journal_add(CPR, more);
time_t changed = p.journal_last_changed(CPR);
TEST_EQUAL_INT(changed, time(NULL), "Changed just now?");
Praxisd::patient_t patient = p.patient_get_by_cpr(CPR);
TEST_EQUAL_STR(patient.fornavne, "Kristian", "Who are you?");
/*
std::string exp = j + more + NL;
std::string j2 = p.journal_get_by_cpr(CPR);
TEST_EQUAL_INT(exp.length(), j2.length(), "Compare lengths");
TEST_EQUAL_STR(exp, j2, "Did we correctly append to the journal?");
*/
p.add_sogeord(CPR, "CA0003", "Nolder");
TEST_END;
#endif/*TEST_PRAXISD*/