1 /**********************************************************
2  * Version $Id$
3  *********************************************************/
4 
5 ///////////////////////////////////////////////////////////
6 //                                                       //
7 //                         SAGA                          //
8 //                                                       //
9 //      System for Automated Geoscientific Analyses      //
10 //                                                       //
11 //           Application Programming Interface           //
12 //                                                       //
13 //                  Library: SAGA_API                    //
14 //                                                       //
15 //-------------------------------------------------------//
16 //                                                       //
17 //                     metadata.cpp                      //
18 //                                                       //
19 //          Copyright (C) 2009 by Olaf Conrad            //
20 //                                                       //
21 //-------------------------------------------------------//
22 //                                                       //
23 // This file is part of 'SAGA - System for Automated     //
24 // Geoscientific Analyses'.                              //
25 //                                                       //
26 // This library is free software; you can redistribute   //
27 // it and/or modify it under the terms of the GNU Lesser //
28 // General Public License as published by the Free       //
29 // Software Foundation, either version 2.1 of the        //
30 // License, or (at your option) any later version.       //
31 //                                                       //
32 // This library is distributed in the hope that it will  //
33 // be useful, but WITHOUT ANY WARRANTY; without even the //
34 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
35 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
36 // License for more details.                             //
37 //                                                       //
38 // You should have received a copy of the GNU Lesser     //
39 // General Public License along with this program; if    //
40 // not, see <http://www.gnu.org/licenses/>.              //
41 //                                                       //
42 //-------------------------------------------------------//
43 //                                                       //
44 //    contact:    Olaf Conrad                            //
45 //                Institute of Geography                 //
46 //                University of Hamburg                  //
47 //                Germany                                //
48 //                                                       //
49 //    e-mail:     oconrad@saga-gis.org                   //
50 //                                                       //
51 ///////////////////////////////////////////////////////////
52 
53 //---------------------------------------------------------
54 
55 ///////////////////////////////////////////////////////////
56 //														 //
57 //														 //
58 //														 //
59 ///////////////////////////////////////////////////////////
60 
61 //---------------------------------------------------------
62 #include <wx/xml/xml.h>
63 #include <wx/wfstream.h>
64 #include <wx/sstream.h>
65 #include <wx/mstream.h>
66 #include <wx/protocol/http.h>
67 
68 #include "metadata.h"
69 #include "table.h"
70 
71 
72 ///////////////////////////////////////////////////////////
73 //														 //
74 //														 //
75 //														 //
76 ///////////////////////////////////////////////////////////
77 
78 //---------------------------------------------------------
CSG_MetaData(void)79 CSG_MetaData::CSG_MetaData(void)
80 {
81 	_On_Construction();
82 }
83 
Create(void)84 bool CSG_MetaData::Create(void)
85 {
86 	return( true );
87 }
88 
89 //---------------------------------------------------------
CSG_MetaData(const CSG_MetaData & MetaData)90 CSG_MetaData::CSG_MetaData(const CSG_MetaData &MetaData)
91 {
92 	_On_Construction();
93 
94 	Create(MetaData);
95 }
96 
Create(const CSG_MetaData & MetaData)97 bool CSG_MetaData::Create(const CSG_MetaData &MetaData)
98 {
99 	return( Assign(MetaData) );
100 }
101 
102 //---------------------------------------------------------
CSG_MetaData(const CSG_String & File,const SG_Char * Extension)103 CSG_MetaData::CSG_MetaData(const CSG_String &File, const SG_Char *Extension)
104 {
105 	_On_Construction();
106 
107 	Create(File, Extension);
108 }
109 
Create(const CSG_String & File,const SG_Char * Extension)110 bool CSG_MetaData::Create(const CSG_String &File, const SG_Char *Extension)
111 {
112 	return( Load(File, Extension) );
113 }
114 
115 //---------------------------------------------------------
CSG_MetaData(CSG_File & Stream)116 CSG_MetaData::CSG_MetaData(CSG_File &Stream)
117 {
118 	_On_Construction();
119 
120 	Create(Stream);
121 }
122 
Create(CSG_File & Stream)123 bool CSG_MetaData::Create(CSG_File &Stream)
124 {
125 	return( Load(Stream) );
126 }
127 
128 //---------------------------------------------------------
CSG_MetaData(CSG_MetaData * pParent)129 CSG_MetaData::CSG_MetaData(CSG_MetaData *pParent)
130 {
131 	_On_Construction();
132 
133 	m_pParent	= pParent;
134 }
135 
136 //---------------------------------------------------------
_On_Construction(void)137 void CSG_MetaData::_On_Construction(void)
138 {
139 	m_pParent	= NULL;
140 
141 	m_Children.Create(sizeof(CSG_MetaData **), 0, SG_ARRAY_GROWTH_1);
142 }
143 
144 //---------------------------------------------------------
~CSG_MetaData(void)145 CSG_MetaData::~CSG_MetaData(void)
146 {
147 	Destroy();
148 }
149 
150 //---------------------------------------------------------
Destroy(void)151 void CSG_MetaData::Destroy(void)
152 {
153 	CSG_MetaData	**m_pChildren	= (CSG_MetaData **)m_Children.Get_Array();
154 
155 	for(int i=0; i<Get_Children_Count(); i++)
156 	{
157 		delete(m_pChildren[i]);
158 	}
159 
160 	m_Children.Destroy();
161 
162 //	m_pParent	= NULL;
163 
164 //	m_Name			.Clear();
165 //	m_Content		.Clear();
166 
167 	m_Prop_Names	.Clear();
168 	m_Prop_Values	.Clear();
169 }
170 
171 
172 ///////////////////////////////////////////////////////////
173 //														 //
174 ///////////////////////////////////////////////////////////
175 
176 //---------------------------------------------------------
Add_Child(void)177 CSG_MetaData * CSG_MetaData::Add_Child(void)
178 {
179 	return( Ins_Child(-1) );
180 }
181 
Add_Child(const CSG_String & Name)182 CSG_MetaData * CSG_MetaData::Add_Child(const CSG_String &Name)
183 {
184 	return( Ins_Child(Name, -1) );
185 }
186 
Add_Child(const CSG_String & Name,const CSG_String & Content)187 CSG_MetaData * CSG_MetaData::Add_Child(const CSG_String &Name, const CSG_String &Content)
188 {
189 	return( Ins_Child(Name, Content, -1) );
190 }
191 
Add_Child(const CSG_String & Name,double Content)192 CSG_MetaData * CSG_MetaData::Add_Child(const CSG_String &Name, double Content)
193 {
194 	return( Ins_Child(Name, SG_Get_String(Content, -16), -1) );
195 }
196 
Add_Child(const CSG_String & Name,int Content)197 CSG_MetaData * CSG_MetaData::Add_Child(const CSG_String &Name, int Content)
198 {
199 	return( Ins_Child(Name, CSG_String::Format(SG_T("%d"), Content), -1) );
200 }
201 
Add_Child(const CSG_MetaData & MetaData,bool bAddChildren)202 CSG_MetaData * CSG_MetaData::Add_Child(const CSG_MetaData &MetaData, bool bAddChildren)
203 {
204 	return( Ins_Child(MetaData, -1, bAddChildren) );
205 }
206 
207 
208 ///////////////////////////////////////////////////////////
209 //														 //
210 ///////////////////////////////////////////////////////////
211 
212 //---------------------------------------------------------
Ins_Child(int Position)213 CSG_MetaData * CSG_MetaData::Ins_Child(int Position)
214 {
215 	if( !m_Children.Inc_Array() )
216 	{
217 		return( NULL );
218 	}
219 
220 	CSG_MetaData	**pChildren	= (CSG_MetaData **)m_Children.Get_Array();
221 
222 	if( Position < 0 || Position >= Get_Children_Count() )
223 	{
224 		Position	= Get_Children_Count() - 1;
225 	}
226 
227 	for(int i=Get_Children_Count()-1; i>Position; i--)
228 	{
229 		pChildren[i]	= pChildren[i - 1];
230 	}
231 
232 	return( pChildren[Position] = new CSG_MetaData(this) );
233 }
234 
235 //---------------------------------------------------------
Ins_Child(const CSG_String & Name,const CSG_String & Content,int Position)236 CSG_MetaData * CSG_MetaData::Ins_Child(const CSG_String &Name, const CSG_String &Content, int Position)
237 {
238 	CSG_MetaData	*pChild	= Ins_Child(Position);
239 
240 	if( pChild )
241 	{
242 		pChild->m_Name		= Name;
243 		pChild->m_Content	= Content;
244 	}
245 
246 	return( pChild );
247 }
248 
Ins_Child(const CSG_String & Name,int Position)249 CSG_MetaData * CSG_MetaData::Ins_Child(const CSG_String &Name, int Position)
250 {
251 	return( Ins_Child(Name, CSG_String(""), Position) );
252 }
253 
Ins_Child(const CSG_String & Name,double Content,int Position)254 CSG_MetaData * CSG_MetaData::Ins_Child(const CSG_String &Name, double Content, int Position)
255 {
256 	return( Ins_Child(Name, SG_Get_String(Content, -16), Position) );
257 }
258 
Ins_Child(const CSG_String & Name,int Content,int Position)259 CSG_MetaData * CSG_MetaData::Ins_Child(const CSG_String &Name, int Content, int Position)
260 {
261 	return( Ins_Child(Name, CSG_String::Format(SG_T("%d"), Content), Position) );
262 }
263 
Ins_Child(const CSG_MetaData & MetaData,int Position,bool bAddChildren)264 CSG_MetaData * CSG_MetaData::Ins_Child(const CSG_MetaData &MetaData, int Position, bool bAddChildren)
265 {
266 	CSG_MetaData	*pChild	= Ins_Child(Position);
267 
268 	if( pChild )
269 	{
270 		pChild->Assign(MetaData, bAddChildren);
271 	}
272 
273 	return( pChild );
274 }
275 
276 
277 ///////////////////////////////////////////////////////////
278 //														 //
279 ///////////////////////////////////////////////////////////
280 
281 //---------------------------------------------------------
Mov_Child(int from_Index,int to_Index)282 bool CSG_MetaData::Mov_Child(int from_Index, int to_Index)
283 {
284 	if( from_Index < 0 || from_Index >= Get_Children_Count()
285 	||    to_Index < 0 ||   to_Index >= Get_Children_Count() )
286 	{
287 		return( false );
288 	}
289 
290 	if( from_Index != to_Index )
291 	{
292 		CSG_MetaData	**pChildren	= (CSG_MetaData **)m_Children.Get_Array();
293 		CSG_MetaData	*pChild	= pChildren[from_Index];
294 
295 		if( from_Index < to_Index )
296 		{
297 			for(int i=from_Index; i<to_Index; i++)
298 			{
299 				pChildren[i]	= pChildren[i + 1];
300 			}
301 		}
302 		else // if( from_Index > to_Index )
303 		{
304 			for(int i=from_Index; i>to_Index; i--)
305 			{
306 				pChildren[i]	= pChildren[i - 1];
307 			}
308 		}
309 
310 		pChildren[to_Index]	= pChild;
311 	}
312 
313 	return( true );
314 }
315 
316 
317 ///////////////////////////////////////////////////////////
318 //														 //
319 ///////////////////////////////////////////////////////////
320 
321 //---------------------------------------------------------
Del_Child(int Index)322 bool CSG_MetaData::Del_Child(int Index)
323 {
324 	if( Index >= 0 && Index < Get_Children_Count() )
325 	{
326 		CSG_MetaData	**pChildren	= (CSG_MetaData **)m_Children.Get_Array();
327 
328 		delete(pChildren[Index]);
329 
330 		for(int i=Index, j=Index+1; j<Get_Children_Count(); i++, j++)
331 		{
332 			pChildren[i]	= pChildren[j];
333 		}
334 
335 		m_Children.Dec_Array();
336 
337 		return( true );
338 	}
339 
340 	return( false );
341 }
342 
343 //---------------------------------------------------------
Add_Children(const CSG_MetaData & MetaData)344 bool CSG_MetaData::Add_Children(const CSG_MetaData &MetaData)
345 {
346 	if( &MetaData != this )
347 	{
348 		for(int i=0; i<MetaData.Get_Children_Count(); i++)
349 		{
350 			Add_Child(MetaData[i], true);
351 		}
352 	}
353 
354 	return( true );
355 }
356 
357 //---------------------------------------------------------
358 /**
359   * Deletes children if depth level is reached, i.e. if depth level equals zero
360   * all children of the node will be deleted, if it is one only the grandchildren
361   * will be affected, and so on.
362   * If Name is a valid string, only those children are taken into account that
363   * have this name.
364 */
365 //---------------------------------------------------------
Del_Children(int Depth,const SG_Char * Name)366 bool CSG_MetaData::Del_Children(int Depth, const SG_Char *Name)
367 {
368 	if( Depth < 0 )
369 	{
370 		// nop
371 	}
372 	else if( Name && *Name )
373 	{
374 		for(int i=Get_Children_Count()-1; i>=0; i--)
375 		{
376 			if( Get_Child(i)->Get_Name().CmpNoCase(Name) )
377 			{
378 				Get_Child(i)->Del_Children(Depth, Name);
379 			}
380 			else if( Depth > 0 )
381 			{
382 				Get_Child(i)->Del_Children(Depth - 1, Name);
383 			}
384 			else
385 			{
386 				Del_Child(i);
387 			}
388 		}
389 	}
390 	else if( Depth > 0 )
391 	{
392 		for(int i=0; i<Get_Children_Count(); i++)
393 		{
394 			Get_Child(i)->Del_Children(Depth - 1, Name);
395 		}
396 	}
397 	else
398 	{
399 		for(int i=0; i<Get_Children_Count(); i++)
400 		{
401 			delete(Get_Child(i));
402 		}
403 
404 		m_Children.Destroy();
405 	}
406 
407 	return( true );
408 }
409 
410 //---------------------------------------------------------
_Get_Child(const CSG_String & Name) const411 int CSG_MetaData::_Get_Child(const CSG_String &Name) const
412 {
413 	for(int i=0; i<Get_Children_Count(); i++)
414 	{
415 		if( Name.CmpNoCase(Get_Child(i)->Get_Name()) == 0 )
416 		{
417 			return( i );
418 		}
419 	}
420 
421 	return( -1 );
422 }
423 
424 
425 ///////////////////////////////////////////////////////////
426 //														 //
427 ///////////////////////////////////////////////////////////
428 
429 //---------------------------------------------------------
Cmp_Name(const CSG_String & String,bool bNoCase) const430 bool CSG_MetaData::Cmp_Name(const CSG_String &String, bool bNoCase) const
431 {
432 	return( bNoCase ? !m_Name.CmpNoCase(String) : !m_Name.Cmp(String) );
433 }
434 
435 
436 ///////////////////////////////////////////////////////////
437 //														 //
438 ///////////////////////////////////////////////////////////
439 
440 //---------------------------------------------------------
Fmt_Content(const char * Format,...)441 void CSG_MetaData::Fmt_Content(const char *Format, ...)
442 {
443 	wxString	s;
444 
445 	va_list	argptr;
446 
447 #ifdef _SAGA_LINUX
448 	wxString	_Format(Format);	_Format.Replace("%s", "%ls");	// workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
449 	va_start(argptr, _Format);
450 	s.PrintfV(_Format, argptr);
451 #else
452 	va_start(argptr, Format);
453 	s.PrintfV(Format, argptr);
454 #endif
455 
456 	m_Content	= CSG_String(&s);
457 
458 	va_end(argptr);
459 }
460 
461 //---------------------------------------------------------
Fmt_Content(const wchar_t * Format,...)462 void CSG_MetaData::Fmt_Content(const wchar_t *Format, ...)
463 {
464 	wxString	s;
465 
466 	va_list	argptr;
467 
468 #ifdef _SAGA_LINUX
469 	wxString	_Format(Format);	_Format.Replace("%s", "%ls");	// workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
470 	va_start(argptr, _Format);
471 	s.PrintfV(_Format, argptr);
472 #else
473 	va_start(argptr, Format);
474 	s.PrintfV(Format, argptr);
475 #endif
476 
477 	m_Content	= CSG_String(&s);
478 
479 	va_end(argptr);
480 }
481 
482 //---------------------------------------------------------
Cmp_Content(const CSG_String & String,bool bNoCase) const483 bool CSG_MetaData::Cmp_Content(const CSG_String &String, bool bNoCase) const
484 {
485 	return( bNoCase ? !m_Content.CmpNoCase(String) : !m_Content.Cmp(String) );
486 }
487 
488 
489 ///////////////////////////////////////////////////////////
490 //														 //
491 ///////////////////////////////////////////////////////////
492 
493 //---------------------------------------------------------
Add_Property(const CSG_String & Name,const CSG_String & Value)494 bool CSG_MetaData::Add_Property(const CSG_String &Name, const CSG_String &Value)
495 {
496 	if( !Value.is_Empty() &&_Get_Property(Name) < 0 )
497 	{
498 		m_Prop_Names .Add(Name );
499 		m_Prop_Values.Add(Value);
500 
501 		return( true );
502 	}
503 
504 	return( false );
505 }
506 
Add_Property(const CSG_String & Name,double Value)507 bool CSG_MetaData::Add_Property(const CSG_String &Name, double Value)
508 {
509 	return( Add_Property(Name, CSG_String::Format(SG_T("%f"), Value)) );
510 }
511 
Add_Property(const CSG_String & Name,int Value)512 bool CSG_MetaData::Add_Property(const CSG_String &Name, int Value)
513 {
514 	return( Add_Property(Name, CSG_String::Format(SG_T("%d"), Value)) );
515 }
516 
517 //---------------------------------------------------------
Del_Property(const CSG_String & Name)518 bool CSG_MetaData::Del_Property(const CSG_String &Name)
519 {
520 	for(int i=0; i<Get_Property_Count(); i++)
521 	{
522 		if( !Get_Property_Name(i).CmpNoCase(Name) )
523 		{
524 			return( Del_Property(i) );
525 		}
526 	}
527 
528 	return( false );
529 }
530 
Del_Property(int i)531 bool CSG_MetaData::Del_Property(int i)
532 {
533 	if( i >= 0 && i < Get_Property_Count() )
534 	{
535 		m_Prop_Names .Del(i);
536 		m_Prop_Values.Del(i);
537 
538 		return( true );
539 	}
540 
541 	return( false );
542 }
543 
544 //---------------------------------------------------------
Set_Property(const CSG_String & Name,const CSG_String & Value,bool bAddIfNotExists)545 bool CSG_MetaData::Set_Property(const CSG_String &Name, const CSG_String &Value, bool bAddIfNotExists)
546 {
547 	int		Index;
548 
549 	if( (Index = _Get_Property(Name)) >= 0 )
550 	{
551 		m_Prop_Values[Index]	= Value;
552 
553 		return( true );
554 	}
555 	else if( bAddIfNotExists )
556 	{
557 		m_Prop_Names	.Add(Name);
558 		m_Prop_Values	.Add(Value);
559 
560 		return( true );
561 	}
562 
563 	return( false );
564 }
565 
Set_Property(const CSG_String & Name,double Value,bool bAddIfNotExists)566 bool CSG_MetaData::Set_Property(const CSG_String &Name, double Value, bool bAddIfNotExists)
567 {
568 	return( Set_Property(Name, CSG_String::Format(SG_T("%f"), Value, bAddIfNotExists)) );
569 }
570 
Set_Property(const CSG_String & Name,int Value,bool bAddIfNotExists)571 bool CSG_MetaData::Set_Property(const CSG_String &Name, int Value, bool bAddIfNotExists)
572 {
573 	return( Set_Property(Name, CSG_String::Format(SG_T("%d"), Value, bAddIfNotExists)) );
574 }
575 
576 //---------------------------------------------------------
Get_Property(const CSG_String & Name,CSG_String & Value) const577 bool CSG_MetaData::Get_Property(const CSG_String &Name, CSG_String &Value)	const
578 {
579 	const SG_Char	*cString	= Get_Property(Name);
580 
581 	if( cString )
582 	{
583 		Value	= cString;
584 
585 		return( true );
586 	}
587 
588 	return( false );
589 }
590 
Get_Property(const CSG_String & Name,double & Value) const591 bool CSG_MetaData::Get_Property(const CSG_String &Name, double &Value)	const
592 {
593 	CSG_String	s;
594 
595 	return( Get_Property(Name, s) && s.asDouble(Value) );
596 }
597 
Get_Property(const CSG_String & Name,int & Value) const598 bool CSG_MetaData::Get_Property(const CSG_String &Name, int &Value)	const
599 {
600 	CSG_String	s;
601 
602 	return( Get_Property(Name, s) && s.asInt(Value) );
603 }
604 
605 //---------------------------------------------------------
Cmp_Property(const CSG_String & Name,const CSG_String & String,bool bNoCase) const606 bool CSG_MetaData::Cmp_Property(const CSG_String &Name, const CSG_String &String, bool bNoCase) const
607 {
608 	CSG_String	s;
609 
610 	return( Get_Property(Name, s) && (bNoCase ? !s.CmpNoCase(String) : !s.Cmp(String)) );
611 }
612 
613 //---------------------------------------------------------
_Get_Property(const CSG_String & Name) const614 int CSG_MetaData::_Get_Property(const CSG_String &Name) const
615 {
616 	for(int i=0; i<m_Prop_Names.Get_Count(); i++)
617 	{
618 		if( Name.CmpNoCase(m_Prop_Names[i]) == 0 )
619 		{
620 			return( i );
621 		}
622 	}
623 
624 	return( -1 );
625 }
626 
627 
628 ///////////////////////////////////////////////////////////
629 //														 //
630 ///////////////////////////////////////////////////////////
631 
632 //---------------------------------------------------------
asText(int Flags) const633 CSG_String CSG_MetaData::asText(int Flags) const
634 {
635 	CSG_String	s;
636 
637 	if( Flags == 0 )
638 	{
639 		for(int i=0; i<Get_Children_Count(); i++)
640 		{
641 			s	+= Get_Child(i)->Get_Name() + ":\t" + Get_Child(i)->Get_Content() + "\n";
642 		}
643 	}
644 	else
645 	{
646 		wxXmlDocument	XML;
647 
648 		wxXmlNode	*pRoot	= new wxXmlNode(NULL, wxXML_ELEMENT_NODE, Get_Name().c_str());
649 
650 		XML.SetRoot(pRoot);
651 
652 		_Save(pRoot);
653 
654 		wxStringOutputStream	Stream;
655 
656 		XML.Save(Stream);
657 
658 		s	= &Stream.GetString();
659 
660 		if( Flags == 2 )	// remove <xml>
661 		{
662 			s	= s.AfterFirst('\n');
663 		}
664 	}
665 
666 	return( s );
667 }
668 
669 //---------------------------------------------------------
Get_Table(int Flags) const670 CSG_Table CSG_MetaData::Get_Table(int Flags) const
671 {
672 	CSG_Table	t;
673 
674 	t.Add_Field("NAME" , SG_DATATYPE_String);
675 	t.Add_Field("VALUE", SG_DATATYPE_String);
676 
677 	for(int i=0; i<Get_Children_Count(); i++)
678 	{
679 		CSG_Table_Record	*r	= t.Add_Record();
680 
681 		r->Set_Value(0, Get_Child(i)->Get_Name());
682 		r->Set_Value(1, Get_Child(i)->Get_Content());
683 	}
684 
685 	return( t );
686 }
687 
688 
689 ///////////////////////////////////////////////////////////
690 //														 //
691 ///////////////////////////////////////////////////////////
692 
693 //---------------------------------------------------------
Assign(const CSG_MetaData & MetaData,bool bAddChildren)694 bool CSG_MetaData::Assign(const CSG_MetaData &MetaData, bool bAddChildren)
695 {
696 	if( &MetaData != this )
697 	{
698 		Destroy();
699 
700 		Set_Name	(MetaData.Get_Name   ());
701 		Set_Content	(MetaData.Get_Content());
702 
703 		for(int i=0; i<MetaData.Get_Property_Count(); i++)
704 		{
705 			Add_Property(MetaData.Get_Property_Name(i), MetaData.Get_Property(i));
706 		}
707 
708 		if( bAddChildren )
709 		{
710 			Add_Children(MetaData);
711 		}
712 	}
713 
714 	return( true );
715 }
716 
717 
718 ///////////////////////////////////////////////////////////
719 //														 //
720 ///////////////////////////////////////////////////////////
721 
722 //---------------------------------------------------------
Load(const CSG_String & File,const SG_Char * Extension)723 bool CSG_MetaData::Load(const CSG_String &File, const SG_Char *Extension)
724 {
725 	Destroy();
726 
727 	//-----------------------------------------------------
728 	if( File.Find("http://") == 0 )
729 	{
730 		CSG_String	s(File.Right(File.Length() - CSG_String("http://").Length()));
731 
732 		return( Load_HTTP(s.BeforeFirst('/'), s.AfterFirst('/')) );
733 	}
734 
735 	//-----------------------------------------------------
736 	CSG_String	_File(SG_File_Make_Path("", File, Extension));
737 
738 	if( !SG_File_Exists(_File) )
739 	{
740 		return( false );
741 	}
742 
743 	//-----------------------------------------------------
744 	if( SG_File_Cmp_Extension(_File, "json") )
745 	{
746 		return( Load_JSON(_File) );
747 	}
748 
749 	//-----------------------------------------------------
750 	wxXmlDocument	XML;
751 
752 	if( XML.Load(_File.c_str()) )
753 	{
754 		_Load(XML.GetRoot());
755 
756 		return( true );
757 	}
758 
759 	//-----------------------------------------------------
760 	return( false );
761 }
762 
763 //---------------------------------------------------------
Load(CSG_File & File)764 bool CSG_MetaData::Load(CSG_File &File)
765 {
766 	Destroy();
767 
768 	wxXmlDocument	XML;
769 
770 	if( File.is_Reading() && XML.Load(*((wxInputStream *)File.Get_Stream())) )
771 	{
772 		_Load(XML.GetRoot());
773 
774 		return( true );
775 	}
776 
777 	return( false );
778 }
779 
780 //---------------------------------------------------------
_Load(wxXmlNode * pNode)781 void CSG_MetaData::_Load(wxXmlNode *pNode)
782 {
783 	m_Name		= pNode->GetName       ().wc_str();
784 	m_Content	= pNode->GetNodeContent().wc_str();
785 
786 	//-----------------------------------------------------
787 	wxXmlAttribute	*pProperty	= pNode->GetAttributes();
788 
789 	while( pProperty )
790 	{
791 		Add_Property(&pProperty->GetName(), &pProperty->GetValue());
792 
793 		pProperty	= pProperty->GetNext();
794 	}
795 
796 	//-----------------------------------------------------
797 	wxXmlNode	*pChild	= pNode->GetChildren();
798 
799 	while( pChild )
800 	{
801 		if( pChild->GetType() != wxXML_TEXT_NODE )
802 		{
803 			Add_Child()->_Load(pChild);
804 		}
805 
806 		pChild	= pChild->GetNext();
807 	}
808 }
809 
810 
811 ///////////////////////////////////////////////////////////
812 //														 //
813 ///////////////////////////////////////////////////////////
814 
815 //---------------------------------------------------------
Save(const CSG_String & File,const SG_Char * Extension) const816 bool CSG_MetaData::Save(const CSG_String &File, const SG_Char *Extension) const
817 {
818 	wxXmlDocument	XML;
819 
820 	wxXmlNode	*pRoot	= new wxXmlNode(NULL, wxXML_ELEMENT_NODE, Get_Name().c_str());
821 
822 	XML.SetRoot(pRoot);
823 
824 	_Save(pRoot);
825 
826 	if( XML.Save(SG_File_Make_Path("", File, Extension).c_str()) )
827 	{
828 		return( true );
829 	}
830 
831 	return( false );
832 }
833 
834 //---------------------------------------------------------
Save(CSG_File & File) const835 bool CSG_MetaData::Save(CSG_File &File) const
836 {
837 	wxXmlDocument	XML;
838 
839 	wxXmlNode	*pRoot	= new wxXmlNode(NULL, wxXML_ELEMENT_NODE, Get_Name().c_str());
840 
841 	XML.SetRoot(pRoot);
842 
843 	_Save(pRoot);
844 
845 	if( File.is_Writing() && XML.Save(*((wxOutputStream *)File.Get_Stream())) )
846 	{
847 		return( true );
848 	}
849 
850 	return( false );
851 }
852 
853 //---------------------------------------------------------
_Save(wxXmlNode * pNode) const854 void CSG_MetaData::_Save(wxXmlNode *pNode) const
855 {
856 	int		i;
857 
858 	//-----------------------------------------------------
859 	pNode->SetName	 (CSG_String(Get_Name().Length() ? Get_Name() : CSG_String("NODE")).c_str());
860 	pNode->SetContent(Get_Content().c_str());
861 
862 	if( Get_Content().Length() > 0 || (Get_Property_Count() == 0 && Get_Children_Count() == 0) )
863 	{
864 		wxXmlNode	*pChild	= new wxXmlNode(pNode, wxXML_TEXT_NODE, SG_T("TEXT"));
865 
866 		pChild->SetContent(Get_Content().c_str());
867 	}
868 
869 	//-----------------------------------------------------
870 	for(i=0; i<Get_Property_Count(); i++)
871 	{
872 		pNode->AddAttribute(Get_Property_Name(i).c_str(), Get_Property(i));
873 	}
874 
875 	//-----------------------------------------------------
876 	for(i=Get_Children_Count()-1; i>=0; i--)
877 	{
878 		Get_Child(i)->_Save(new wxXmlNode(pNode, wxXML_ELEMENT_NODE, Get_Child(i)->Get_Name().c_str()));
879 	}
880 }
881 
882 
883 ///////////////////////////////////////////////////////////
884 //														 //
885 ///////////////////////////////////////////////////////////
886 
887 //---------------------------------------------------------
from_XML(const CSG_String & _XML)888 bool CSG_MetaData::from_XML(const CSG_String &_XML)
889 {
890 	Destroy();
891 
892 	wxXmlDocument	XML;
893 
894 	wxMemoryInputStream	Stream((const void *)_XML.b_str(), (size_t)_XML.Length());
895 
896 	if( XML.Load(Stream) )
897 	{
898 		_Load(XML.GetRoot());
899 
900 		return( true );
901 	}
902 
903 	return( false );
904 }
905 
906 //---------------------------------------------------------
to_XML(CSG_String & _XML) const907 bool CSG_MetaData::to_XML(CSG_String &_XML) const
908 {
909 	wxXmlDocument	XML;
910 
911 	wxXmlNode	*pRoot	= new wxXmlNode(NULL, wxXML_ELEMENT_NODE, Get_Name().c_str());
912 
913 	XML.SetRoot(pRoot);
914 
915 	_Save(pRoot);
916 
917 	wxMemoryOutputStream	Stream;
918 
919 	if( XML.Save(Stream) )
920 	{
921 		CSG_Array	s(sizeof(char), Stream.GetSize());
922 
923 		Stream.CopyTo(s.Get_Array(), s.Get_Size());
924 
925 		_XML	= (const char *)s.Get_Array();
926 
927 		return( true );
928 	}
929 
930 	return( false );
931 }
932 
933 
934 ///////////////////////////////////////////////////////////
935 //														 //
936 ///////////////////////////////////////////////////////////
937 
938 //---------------------------------------------------------
Load_HTTP(const CSG_String & Server,const CSG_String & Path,const SG_Char * Username,const SG_Char * Password)939 bool CSG_MetaData::Load_HTTP(const CSG_String &Server, const CSG_String &Path, const SG_Char *Username, const SG_Char *Password)
940 {
941 	Destroy();
942 
943 	//-----------------------------------------------------
944 	wxHTTP	HTTP;
945 
946 	if( Username && *Username )	{	HTTP.SetUser    (Username);	}
947 	if( Password && *Password )	{	HTTP.SetPassword(Password);	}
948 
949 	wxString	s	= Server.c_str();
950 
951 	if( s.Find("http://") == 0 )
952 	{
953 		s	= s.Right(s.Length() - wxString("http://").Length());
954 	}
955 
956 	if( !HTTP.Connect(s) )
957 	{
958 		return( false );
959 	}
960 
961 	//-----------------------------------------------------
962 	s	= Path.c_str();
963 
964 	if( s[0] != '/' )
965 	{
966 		s.Prepend("/");
967 	}
968 
969 	wxInputStream	*pStream	= HTTP.GetInputStream(s);
970 
971 	if( !pStream )
972 	{
973 		return( false );
974 	}
975 
976 	wxXmlDocument	XML;
977 
978 	if( XML.Load(*pStream) )
979 	{
980 		_Load(XML.GetRoot());
981 
982 		delete(pStream);
983 
984 		return( true );
985 	}
986 
987 	delete(pStream);
988 
989 	return( false );
990 }
991 
992 
993 ///////////////////////////////////////////////////////////
994 //														 //
995 ///////////////////////////////////////////////////////////
996 
997 //---------------------------------------------------------
from_WKT(const CSG_String & WKT)998 bool CSG_MetaData::from_WKT(const CSG_String &WKT)
999 {
1000 	return( false );
1001 }
1002 
1003 //---------------------------------------------------------
to_WKT(CSG_String & WKT) const1004 bool CSG_MetaData::to_WKT(CSG_String &WKT) const
1005 {
1006 	return( false );
1007 }
1008 
1009 
1010 ///////////////////////////////////////////////////////////
1011 //														 //
1012 ///////////////////////////////////////////////////////////
1013 
1014 //---------------------------------------------------------
Load_JSON(const CSG_String & File)1015 bool CSG_MetaData::Load_JSON(const CSG_String &File)
1016 {
1017 	CSG_File	Stream;	CSG_String	JSON;
1018 
1019 	if( Stream.Open(File, SG_FILE_R, false) && Stream.Read(JSON, (size_t)Stream.Length()) > 0 )
1020 	{
1021 		return( from_JSON(JSON) );
1022 	}
1023 
1024 	return( false );
1025 }
1026 
1027 //---------------------------------------------------------
Save_JSON(const CSG_String & File) const1028 bool CSG_MetaData::Save_JSON(const CSG_String &File)	const
1029 {
1030 	return( false );
1031 }
1032 
1033 //---------------------------------------------------------
from_JSON(const CSG_String & JSON)1034 bool CSG_MetaData::from_JSON(const CSG_String &JSON)
1035 {
1036 	Destroy();
1037 
1038 	Set_Name("root");
1039 
1040 	CSG_MetaData	*pNode	= this;
1041 
1042 	const SG_Char	*pc	= JSON.c_str();
1043 
1044 	while( *pc )
1045 	{
1046 		CSG_String	Element;
1047 
1048 		for(bool bQuota=false;;)
1049 		{
1050 			SG_Char c = *pc++;
1051 
1052 			if( !c || c == '\n' ) { break; } else
1053 			{
1054 				if( c == '\"' )
1055 				{
1056 					Element += c; bQuota = !bQuota;
1057 				}
1058 				else if( bQuota || (c != ' ' && c != '\t' && c != ',') )
1059 				{
1060 					Element += c;
1061 				}
1062 			}
1063 		}
1064 
1065 		//-------------------------------------------------
1066 		if( Element.is_Empty() )
1067 		{
1068 			// nop
1069 		}
1070 		else if( Element.Find('[') >= 0 )	// array begins
1071 		{
1072 			pNode	= pNode->Add_Child(Element.AfterFirst('\"').BeforeFirst('\"'));
1073 
1074 			pNode->Add_Property("array", 1);
1075 		}
1076 		else if( Element.Find(']') >= 0 )	// array ends
1077 		{
1078 			if( pNode != this )
1079 			{
1080 				pNode	= pNode->Get_Parent();
1081 			}
1082 		}
1083 		else if( Element.Find('{') >= 0 )	// object begins
1084 		{
1085 			Element	= Element.AfterFirst('\"').BeforeFirst('\"');
1086 
1087 			if( !Element.is_Empty() )
1088 			{
1089 				pNode	= pNode->Add_Child(Element);
1090 			}
1091 			else if( pNode->Get_Property("array") )
1092 			{
1093 				pNode	= pNode->Add_Child(CSG_String::Format("%d", pNode->Get_Children_Count()));
1094 			}
1095 		}
1096 		else if( Element.Find('}') >= 0 )	// object ends
1097 		{
1098 			if( pNode != this )
1099 			{
1100 				pNode	= pNode->Get_Parent();
1101 			}
1102 		}
1103 		else
1104 		{
1105 			CSG_String	Key  (Element.AfterFirst('\"').BeforeFirst('\"'));
1106 			CSG_String	Value(Element.AfterFirst(':'));
1107 
1108 			if( Value.Find('\"') > -1 )
1109 			{
1110 				Value	= Value.AfterFirst('\"').BeforeFirst('\"');
1111 			}
1112 
1113 			pNode->Add_Child(Key, Value);
1114 		}
1115 	}
1116 
1117 	return( true );
1118 }
1119 
1120 //---------------------------------------------------------
to_JSON(CSG_String & JSON) const1121 bool CSG_MetaData::to_JSON(CSG_String &JSON)	const
1122 {
1123 	return( false );
1124 }
1125 
1126 
1127 ///////////////////////////////////////////////////////////
1128 //														 //
1129 //														 //
1130 //														 //
1131 ///////////////////////////////////////////////////////////
1132 
1133 //---------------------------------------------------------
CSG_HTTP(void)1134 CSG_HTTP::CSG_HTTP(void)
1135 {
1136 	m_pHTTP	= NULL;
1137 }
1138 
1139 //---------------------------------------------------------
Create(void)1140 bool CSG_HTTP::Create(void)
1141 {
1142 	return( Destroy() );
1143 }
1144 
1145 //---------------------------------------------------------
CSG_HTTP(const CSG_String & Server,const SG_Char * Username,const SG_Char * Password)1146 CSG_HTTP::CSG_HTTP(const CSG_String &Server, const SG_Char *Username, const SG_Char *Password)
1147 {
1148 	m_pHTTP	= NULL;
1149 
1150 	Create(Server, Username, Password);
1151 }
1152 
1153 //---------------------------------------------------------
Create(const CSG_String & Server,const SG_Char * Username,const SG_Char * Password)1154 bool CSG_HTTP::Create(const CSG_String &Server, const SG_Char *Username, const SG_Char *Password)
1155 {
1156 	Destroy();
1157 
1158 	m_pHTTP	= new wxHTTP;
1159 
1160 	if( Username && *Username )	{	m_pHTTP->SetUser    (Username);	}
1161 	if( Password && *Password )	{	m_pHTTP->SetPassword(Password);	}
1162 
1163 	wxString	Host	= Server.c_str();
1164 
1165 	unsigned short	Port	= 80;
1166 
1167 	#define SERVER_TRIM(s, p)	{ wxString sp(p); sp += "://"; if( s.Find(p) == 0 ) { s = s.Right(s.Length() - sp.Length()); } }
1168 
1169 	SERVER_TRIM(Host, "https");
1170 	SERVER_TRIM(Host, "http");
1171 
1172 	if( Host.Find(":") >= 0 )
1173 	{
1174 		long	_Port;
1175 
1176 		if( Host.AfterLast(':').ToLong(&_Port) )
1177 		{
1178 			Port	= (unsigned short)_Port;
1179 		}
1180 
1181 		Host	= Host.BeforeLast(':');
1182 	}
1183 
1184 	if( !m_pHTTP->Connect(Host, Port) )
1185 	{
1186 		Destroy();
1187 
1188 		return( false );
1189 	}
1190 
1191 	return( true );
1192 }
1193 
1194 //---------------------------------------------------------
~CSG_HTTP(void)1195 CSG_HTTP::~CSG_HTTP(void)
1196 {
1197 	Destroy();
1198 }
1199 
1200 //---------------------------------------------------------
Destroy(void)1201 bool CSG_HTTP::Destroy(void)
1202 {
1203 	if( m_pHTTP )
1204 	{
1205 		delete(m_pHTTP);
1206 
1207 		m_pHTTP	= NULL;
1208 	}
1209 
1210 	return( true );
1211 }
1212 
1213 //---------------------------------------------------------
is_Connected(void) const1214 bool CSG_HTTP::is_Connected(void)	const
1215 {
1216 	return( m_pHTTP != NULL );
1217 }
1218 
1219 //---------------------------------------------------------
_Request(const CSG_String & Request)1220 wxInputStream * CSG_HTTP::_Request(const CSG_String &Request)
1221 {
1222 	if( !is_Connected() )
1223 	{
1224 		return( NULL );
1225 	}
1226 
1227 	wxString	s(Request.c_str());
1228 
1229 	if( s[0] != '/' )
1230 	{
1231 		s.Prepend("/");
1232 	}
1233 
1234 	wxInputStream	*pStream	= m_pHTTP->GetInputStream(s);
1235 
1236 	if( pStream && !pStream->CanRead() )
1237 	{
1238 		delete(pStream);
1239 
1240 		return( NULL );
1241 	}
1242 
1243 	return( pStream );
1244 }
1245 
1246 //---------------------------------------------------------
Request(const CSG_String & Request,CSG_MetaData & Answer)1247 bool CSG_HTTP::Request(const CSG_String &Request, CSG_MetaData &Answer)
1248 {
1249 	wxInputStream *pStream = _Request(Request); if( !pStream ) { return( false ); }
1250 
1251 	wxXmlDocument	XML;
1252 
1253 	if( !XML.Load(*pStream) )
1254 	{
1255 		delete(pStream);
1256 
1257 		return( false );
1258 	}
1259 
1260 	Answer.Destroy();	Answer._Load(XML.GetRoot());
1261 
1262 	delete(pStream);
1263 
1264 	return( true );
1265 }
1266 
1267 //---------------------------------------------------------
Request(const CSG_String & Request,CSG_Bytes & Answer)1268 bool CSG_HTTP::Request(const CSG_String &Request, CSG_Bytes &Answer)
1269 {
1270 	wxInputStream *pStream = _Request(Request); if( !pStream ) { return( false ); }
1271 
1272 //	if( pStream->GetSize() == ((size_t)-1) )
1273 //	{
1274 //		delete(pStream);
1275 //
1276 //		return( false );
1277 //	}
1278 
1279 	Answer.Clear();
1280 
1281 	while( pStream->CanRead() )
1282 	{
1283 		char	Byte;
1284 
1285 		pStream->Read(&Byte, sizeof(Byte));
1286 
1287 		Answer	+= Byte;
1288 	}
1289 
1290 	delete(pStream);
1291 
1292 	return( true );
1293 }
1294 
1295 //---------------------------------------------------------
Request(const CSG_String & Request,CSG_String & Answer)1296 bool CSG_HTTP::Request(const CSG_String &Request, CSG_String &Answer)
1297 {
1298 	wxInputStream *pStream = _Request(Request); if( !pStream ) { return( false ); }
1299 
1300 	//if( pStream->GetSize() == ((size_t)-1) )
1301 	//{
1302 	//	delete(pStream);
1303 
1304 	//	return( false );
1305 	//}
1306 
1307 	Answer.Clear();
1308 
1309 	while( pStream->CanRead() )
1310 	{
1311 		char	Byte;
1312 
1313 		pStream->Read(&Byte, sizeof(Byte));
1314 
1315 		Answer	+= Byte;
1316 	}
1317 
1318 	delete(pStream);
1319 
1320 	return( true );
1321 }
1322 
1323 //---------------------------------------------------------
Request(const CSG_String & Request,const SG_Char * File)1324 bool CSG_HTTP::Request(const CSG_String &Request, const SG_Char *File)
1325 {
1326 	wxInputStream *pStream = _Request(Request); if( !pStream ) { return( false ); }
1327 
1328 	wxFileOutputStream	*pFile	= new wxFileOutputStream(File);
1329 
1330 	if( !pFile )
1331 	{
1332 		delete(pStream);
1333 
1334 		return( false );
1335 	}
1336 
1337 	pFile->Write(*pStream);
1338 
1339 	delete(pFile);
1340 
1341 	delete(pStream);
1342 
1343 	return( true );
1344 }
1345 
1346 
1347 ///////////////////////////////////////////////////////////
1348 //														 //
1349 //														 //
1350 //														 //
1351 ///////////////////////////////////////////////////////////
1352 
1353 //---------------------------------------------------------
1354 #include <wx/protocol/ftp.h>
1355 
1356 //---------------------------------------------------------
SG_FTP_Download(const CSG_String & Target_Directory,const CSG_String & Source,const SG_Char * Username,const SG_Char * Password,unsigned short Port,bool bBinary,bool bVerbose)1357 bool	SG_FTP_Download(const CSG_String &Target_Directory, const CSG_String &Source, const SG_Char *Username, const SG_Char *Password, unsigned short Port, bool bBinary, bool bVerbose)
1358 {
1359 	CSG_String	_Source(Source); _Source.Trim();
1360 
1361 	if( _Source.Find("ftp://") == 0 )
1362 	{
1363 		_Source	= _Source.Right(_Source.Length() - CSG_String("ftp://").Length());
1364 	}
1365 
1366 	CSG_String	ftpHost	= _Source.BeforeFirst('/');
1367 	CSG_String	ftpDir	= _Source.AfterFirst ('/').BeforeLast('/'); // ftpDir.Prepend("/");
1368 	CSG_String	ftpFile	= _Source.AfterLast  ('/');
1369 
1370 	//-----------------------------------------------------
1371 	wxFTP ftp;
1372 
1373 	if( Username && *Username )	{	ftp.SetUser    (Username);	}
1374 	if( Password && *Password )	{	ftp.SetPassword(Password);	}
1375 
1376 	if( !ftp.Connect(ftpHost.c_str(), Port) )
1377 	{
1378 		if( bVerbose )
1379 		{
1380 			SG_UI_Msg_Add_Error(_TL("Couldn't connect"));
1381 		}
1382 
1383 		return( false );
1384 	}
1385 
1386 	//-----------------------------------------------------
1387 	if( !ftpDir.is_Empty() && !ftp.ChDir(ftpDir.c_str()) )
1388 	{
1389 		if( bVerbose )
1390 		{
1391 			SG_UI_Msg_Add_Error(CSG_String::Format("%s [%s]", _TL("Couldn't change to directory"), ftpDir.c_str()));
1392 		}
1393 
1394 		return( false );
1395 	}
1396 
1397 	if( ftp.GetFileSize(ftpFile.c_str()) == -1 )
1398 	{
1399 		if( bVerbose )
1400 		{
1401 			SG_UI_Msg_Add_Error(CSG_String::Format("%s [%s]", _TL("Couldn't get the file size"), ftpFile.c_str()));
1402 		}
1403 	}
1404 
1405 	//-----------------------------------------------------
1406 	wxInputStream	*pStream	= ftp.GetInputStream(ftpFile.c_str());
1407 
1408 	if( !pStream )
1409 	{
1410 		if( bVerbose )
1411 		{
1412 			SG_UI_Msg_Add_Error(CSG_String::Format("%s [%s]", _TL("Couldn't get the file"), ftpFile.c_str()));
1413 		}
1414 
1415 		return( false );
1416 	}
1417 
1418 	//-----------------------------------------------------
1419 	wxFileOutputStream	*pFile	= new wxFileOutputStream(SG_File_Make_Path(Target_Directory, ftpFile).c_str());
1420 
1421 	if( !pFile )
1422 	{
1423 		if( bVerbose )
1424 		{
1425 			SG_UI_Msg_Add_Error(CSG_String::Format("%s [%s]", _TL("Couldn't create target file"), SG_File_Make_Path(Target_Directory, ftpFile).c_str()));
1426 		}
1427 
1428 		delete(pStream);
1429 
1430 		return( false );
1431 	}
1432 
1433 	//-----------------------------------------------------
1434 	pFile->Write(*pStream);
1435 
1436 	delete(pFile);
1437 	delete(pStream);
1438 
1439 	return( true );
1440 }
1441 
1442 
1443 ///////////////////////////////////////////////////////////
1444 //														 //
1445 //														 //
1446 //														 //
1447 ///////////////////////////////////////////////////////////
1448 
1449 //---------------------------------------------------------
1450