32#include "peer_client.h"
34#include <wx/fileconf.h>
35#include <wx/json_defs.h>
36#include <wx/jsonreader.h>
37#include <wx/tokenzr.h>
39#include "config_vars.h"
42#include "nav_object_database.h"
43#include "REST_server.h"
45extern std::string PINtoRandomKeyString(
int dpin);
49wxString GetErrorText(
int result){
51 case RESTServerResult::RESULT_GENERIC_ERROR:
52 return _(
"Server Generic Error");
53 case RESTServerResult::RESULT_OBJECT_REJECTED:
54 return _(
"Peer rejected object");
55 case RESTServerResult::RESULT_DUPLICATE_REJECTED:
56 return _(
"Peer rejected duplicate object");
57 case RESTServerResult::RESULT_ROUTE_INSERT_ERROR:
58 return _(
"Peer internal error (insert)");
60 return _(
"Server Unknown Error");
64size_t wxcurl_string_write_UTF8(
void* ptr,
size_t size,
size_t nmemb,
void* pcharbuf)
66 size_t iRealSize = size * nmemb;
67 wxCharBuffer* pStr = (wxCharBuffer*) pcharbuf;
72 wxString str1a = wxString(*pStr);
73 wxString str2 = wxString((
const char*)ptr, wxConvUTF8, iRealSize);
74 *pStr = (str1a + str2).mb_str();
76 wxString str = wxString(*pStr, wxConvUTF8) + wxString((
const char*)ptr, wxConvUTF8, iRealSize);
77 *pStr = str.mb_str(wxConvUTF8);
91WriteMemoryCallback(
void *contents,
size_t size,
size_t nmemb,
void *userp)
93 size_t realsize = size * nmemb;
96 char *ptr = (
char *)realloc(mem->memory, mem->size + realsize + 1);
99 printf(
"not enough memory (realloc returned NULL)\n");
104 memcpy(&(mem->memory[mem->size]), contents, realsize);
105 mem->size += realsize;
106 mem->memory[mem->size] = 0;
111long PostSendObjectMessage( std::string url, std::ostringstream &body,
114 long response_code = -1;
120 CURL* c = curl_easy_init();
121 curl_easy_setopt(c, CURLOPT_ENCODING,
"identity");
122 curl_easy_setopt(c, CURLOPT_URL, url.c_str());
123 curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0L);
124 curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 0L);
126 int iSize = strlen(body.str().c_str());
127 curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, iSize);
128 curl_easy_setopt(c, CURLOPT_COPYPOSTFIELDS, body.str().c_str());
130 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
131 curl_easy_setopt(c, CURLOPT_WRITEDATA, (
void *)response);
133 CURLcode result = curl_easy_perform(c);
135 if(result == CURLE_OK)
136 curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &response_code);
138 curl_easy_cleanup(c);
141 return response_code;
144std::string GetClientKey( std::string &server_name )
146 if (TheBaseConfig()) {
147 TheBaseConfig()->SetPath(
"/Settings/RESTClient");
151 TheBaseConfig()->Read(
"ServerKeys", &key_string );
152 wxStringTokenizer st(key_string, _T(
";"));
153 while (st.HasMoreTokens()) {
154 wxString s1 = st.GetNextToken();
155 wxString server_name_persisted = s1.BeforeFirst(
':');
156 wxString server_key = s1.AfterFirst(
':');
158 if (!server_name_persisted.ToStdString().compare(server_name))
159 return server_key.ToStdString();
165void SaveClientKey( std::string &server_name, std::string key )
167 if (TheBaseConfig()) {
168 TheBaseConfig()->SetPath(
"/Settings/RESTClient");
172 TheBaseConfig()->Read(
"ServerKeys", &key_string );
173 wxStringTokenizer st(key_string, _T(
";"));
174 while (st.HasMoreTokens()) {
175 wxString s1 = st.GetNextToken();
179 bool b_updated =
false;
180 for (
unsigned int i=0; i<array.GetCount(); i++){
181 wxString s1 = array[i];
182 wxString server_name_persisted = s1.BeforeFirst(
':');
183 wxString server_key = s1.AfterFirst(
':');
184 if (server_name_persisted.IsSameAs(server_name.c_str())){
185 array[i] = server_name_persisted +
":" + key.c_str();
192 wxString new_entry = server_name.c_str() + wxString(
":") + key.c_str();
193 array.Add(new_entry);
196 wxString key_string_updated;
197 for (
unsigned int i=0; i<array.GetCount(); i++){
198 wxString s1 = array[i];
199 key_string_updated += s1;
200 key_string_updated +=
";";
203 TheBaseConfig()->Write(
"ServerKeys", key_string_updated );
211int SendRoute(std::string dest_ip_address, std::string server_name, std::vector<Route*> route, std::vector<RoutePoint*> routepoint, std::vector<Track*> track,
bool overwrite)
213 if(route.empty() && routepoint.empty() && track.empty())
218 for (
auto r : route) {
219 pgpx->AddGPXRoute(r);
221 for (
auto r : routepoint) {
222 pgpx->AddGPXWaypoint(r);
224 for (
auto r : track) {
225 pgpx->AddGPXTrack(r);
227 std::ostringstream stream;
228 pgpx->save(stream, PUGIXML_TEXT(
" "));
230 bool apikey_ok =
false;
231 bool b_cancel =
false;
233 while (!apikey_ok && b_cancel ==
false){
234 std::string api_key = GetClientKey(server_name);
236 std::string url(dest_ip_address);
237 url +=
"/api/rx_object";
238 url += std::string(
"?source=") + g_hostname;
239 url += std::string(
"&apikey=") + api_key;
242 chunk.memory = (
char *)malloc(1);
245 long response_code = PostSendObjectMessage( url, stream, &chunk);
247 if(response_code == 200){
248 wxString body(chunk.memory);
252 int numErrors = reader.Parse( body, &root );
254 int result = root[
"result"].AsInt();
256 if (result == RESULT_NEW_PIN_REQUESTED){
259 PINConfirmDialog dlg((wxWindow *)gFrame, wxID_ANY, _(
"OpenCPN Server Message"),
260 "", wxDefaultPosition, wxDefaultSize, SYMBOL_PCD_STYLE );
262 wxString hmsg(
"The server ");
263 hmsg +=
"needs a PIN.\nPlease enter the PIN number from ";
264 hmsg += wxString(
"the server ");
265 hmsg +=
" to pair with this device.\n";
267 dlg.SetMessage(hmsg);
268 dlg.SetText1Message(
"");
270 if (dlg.ShowModal() == ID_PCD_OK) {
271 wxString PIN_tentative = dlg.GetText1Value().Trim().Trim(
false);
272 unsigned int dPIN = atoi(PIN_tentative.ToStdString().c_str());
273 std::string new_api_key = PINtoRandomKeyString(dPIN);;
275 SaveClientKey(server_name, new_api_key);
281 wxString error_text = GetErrorText(result);
283 wxICON_ERROR | wxOK);
293 err_msg.Printf(
"Server HTTP response is: %ld", response_code);
295 wxICON_ERROR | wxOK);
307 EVT_BUTTON(ID_PCD_CANCEL, PINConfirmDialog::OnCancelClick)
308 EVT_BUTTON(ID_PCD_OK, PINConfirmDialog::OnOKClick)
313 m_CancelButton = NULL;
317PINConfirmDialog::PINConfirmDialog(wxWindow* parent, wxWindowID
id,
318 const wxString& caption,
const wxString& hint,
319 const wxPoint& pos,
const wxSize& size,
long style) {
320 wxFont* pif = FontMgr::Get().GetFont(_T(
"Dialog"));
322 Create(parent,
id, caption, hint, pos, size, style);
325PINConfirmDialog::~PINConfirmDialog() {
327 delete m_CancelButton;
330bool PINConfirmDialog::Create(wxWindow* parent, wxWindowID
id,
331 const wxString& caption,
const wxString& hint,
332 const wxPoint& pos,
const wxSize& size,
long style) {
333 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
334 wxDialog::Create(parent,
id, caption, pos, size, style);
336 CreateControls(hint);
337 GetSizer()->Fit(
this);
338 GetSizer()->SetSizeHints(
this);
344void PINConfirmDialog::CreateControls(
const wxString& hint) {
347 wxBoxSizer* itemBoxSizer2 =
new wxBoxSizer(wxVERTICAL);
348 SetSizer(itemBoxSizer2);
352 itemBoxSizer2->AddSpacer(20);
354 premtext =
new wxStaticText(
this, -1,
"A loooooooooooooooooooooooooooooooooooooooooooooong line\n");
355 itemBoxSizer2->Add(premtext, 0, wxEXPAND | wxALL, 10);
357 m_pText1 =
new wxTextCtrl(
this, wxID_ANY,
" ",
358 wxDefaultPosition, wxDefaultSize, wxTE_CENTRE);
359 itemBoxSizer2->Add(m_pText1, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 10);
363 wxBoxSizer* itemBoxSizer16 =
new wxBoxSizer(wxHORIZONTAL);
364 itemBoxSizer2->Add(itemBoxSizer16, 0, wxALIGN_RIGHT | wxALL, 5);
366 m_CancelButton =
new wxButton(itemDialog1, ID_PCD_CANCEL, _(
"Cancel"),
367 wxDefaultPosition, wxDefaultSize, 0);
368 itemBoxSizer16->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
370 m_OKButton =
new wxButton(itemDialog1, ID_PCD_OK,
"OK",
371 wxDefaultPosition, wxDefaultSize, 0);
372 itemBoxSizer16->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
373 m_OKButton->SetDefault();
376void PINConfirmDialog::SetMessage(
const wxString &msg) {
378 premtext->SetLabel(msg);
379 premtext->Refresh(
true);
383void PINConfirmDialog::SetText1Message(
const wxString &msg) {
384 m_pText1->ChangeValue(msg);
386 GetSizer()->Fit(
this);
389void PINConfirmDialog::OnOKClick(wxCommandEvent& event) {
393void PINConfirmDialog::OnCancelClick(wxCommandEvent& event) {
394 EndModal(ID_PCD_CANCEL);