source: branches/work_311/ARInside.cpp @ 623

Revision 623, 45.2 KB checked in by jls17, 5 years ago (diff)
  • program switches to slow object loading automatically if server version is below 6.3
  • changed CARFieldListServer and CARVUIListServer to take slowObjectLoading option into account
Line 
1//Copyright (C) 2009 Stefan Nerlich | stefan.nerlich@hotmail.com
2//
3//This file is part of ARInside.
4//
5//    ARInside is free software: you can redistribute it and/or modify
6//    it under the terms of the GNU General Public License as published by
7//    the Free Software Foundation, version 2 of the License.
8//
9//    ARInside is distributed in the hope that it will be useful,
10//    but WITHOUT ANY WARRANTY; without even the implied warranty of
11//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12//    GNU General Public License for more details.
13//
14//    You should have received a copy of the GNU General Public License
15//    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
16
17#include "stdafx.h"
18#include "ARInside.h"
19
20#include "core/ChangeHistoryEntry.h"
21#include "core/ARHandle.h"
22#include "core/ARStatusList.h"
23
24#include "doc/DocMain.h"
25#include "doc/DocUserDetails.h"
26#include "doc/DocGroupDetails.h"
27#include "doc/DocSchemaDetails.h"
28#include "doc/DocAlDetails.h"
29#include "doc/DocFilterDetails.h"
30#include "doc/DocEscalationDetails.h"
31#include "doc/DocCharMenuDetails.h"
32#include "doc/DocFieldDetails.h"
33#include "doc/DocVuiDetails.h"
34#include "doc/DocWebserviceDetails.h"
35#include "doc/DocPacklistDetails.h"
36#include "doc/DocApplicationDetails.h"
37#include "doc/DocAlGuideDetails.h"
38#include "doc/DocFilterGuideDetails.h"
39#include "doc/DocContainerHelper.h"
40#include "doc/DocAnalyzer.h"
41#include "doc/DocValidator.h"
42#include "doc/DocRoleDetails.h"
43#include "doc/DocSummaryInfo.h"
44#include "doc/DocImageDetails.h"
45#include "doc/DocImageOverview.h"
46#include "doc/DocCustomWorkflow.h"
47#include "doc/DocTextReferences.h"
48
49#include "output/ObjNotFound.h"
50#include "output/ImageTag.h"
51#include "output/Table.h"
52#include "output/WebUtil.h"
53#include "output/NavigationPage.h"
54
55#include "output/IFileStructure.h"
56#include "output/FileNaming.h"
57#include "output/URLLink.h"
58
59#include "scan/ScanMain.h"
60
61#include "util/ResourceFileLocatorAndExtractor.h"
62#include "util/Context.h"
63
64/////////
65// the following file is generated via a pre-build step using "svnrev_template.h" as template.
66// The $WCREV$ keyword of the template is replaced with the revision number.
67#include "svnrev.h"
68
69/////////
70// version information block
71#define VERSION "3.1.1"
72#if defined(_DEBUG)
73#define VERSION_STR VERSION "." SVN_REV_STR " Debug"
74#elif defined(_ARINSIDE_BETA)
75#define VERSION_STR VERSION "." SVN_REV_STR " Beta"
76#else
77#define VERSION_STR VERSION "." SVN_REV_STR
78#endif
79const string AppVersion = VERSION_STR;
80/////////
81
82
83using namespace OUTPUT;
84
85// some kind of singleton pattern to keep compatibility
86CARInside* CARInside::pInsideInstance = NULL;
87
88CARInside::CARInside(AppConfig &appConfig)
89{
90        this->appConfig = appConfig;
91        this->globalFieldList.clear();
92        this->overlayMode = 1; // TODO: this is the default value for ars764. check for later versions
93
94        this->nDurationLoad = 0;
95        this->nDurationDocumentation = 0;
96
97        this->vMajor = 0;
98        this->vMinor = 0;
99        this->vRevision = 0;
100        this->arXmlVersion = 0;
101
102        if (appConfig.oldNaming)
103                SetFileNamingStrategy(new FileNaming::DefaultFileNamingStrategy());
104        else
105                SetFileNamingStrategy(new FileNaming::ObjectNameFileNamingStrategy());
106
107        if (CARInside::pInsideInstance == NULL) 
108                CARInside::pInsideInstance = this;
109
110        ARZeroMemory(&emptyPropList); // init struct; see lists/ARListHelpers.h
111}
112
113CARInside::~CARInside(void)
114{
115        DestroyFileNamingStrategy();
116}
117
118int CARInside::Init(string user, string pw, string server, int port, int rpc)
119{
120        cout << endl << "Connecting to server " << server << "..." << endl;
121
122        ARStatusList status;
123
124        ARZeroMemory(&arControl);
125        ARZeroMemory(&status);
126
127        if(this->appConfig.bUseUtf8)
128                strcpy(arControl.localeInfo.charSet, "UTF-8");
129
130        strncpy(arControl.user, user.c_str(), AR_MAX_NAME_SIZE);
131        arControl.user[AR_MAX_NAME_SIZE]='\0';
132        strncpy(arControl.password, pw.c_str(), AR_MAX_PASSWORD_SIZE);
133        arControl.password[AR_MAX_PASSWORD_SIZE]='\0';
134        strncpy(arControl.server, server.c_str(), AR_MAX_SERVER_SIZE);
135        arControl.server[AR_MAX_SERVER_SIZE]='\0';
136
137        int nResult = ARInitialization(&this->arControl,&status);
138        if (nResult != AR_RETURN_OK)
139        {
140                cout << "Initilization of ARAPI returned: " << nResult << " (" << CAREnum::ActiveLinkMessageType(nResult) << ")" << endl;
141                cout << BuildMessageAndFreeStatus(status);
142                return nResult;
143        }
144
145        if(server == "" && nResult == AR_RETURN_OK) // Filemode
146        {
147                return AR_RETURN_OK;
148        }
149
150        if ( nResult == AR_RETURN_OK)
151        {
152                if(port>0)
153                {
154                        nResult = ARSetServerPort(&this->arControl, this->arControl.server, port, rpc, &status);
155                        if (nResult != AR_RETURN_OK)
156                        {
157                                throw(AppException(BuildMessageAndFreeStatus(status), "undefined", "ARSystem"));
158                        }
159                }
160
161                if(this->appConfig.apiTimeout > 120) // at least 120 seconds api timeout
162                {
163                        ARValueStruct val; 
164                        for (unsigned int valId = AR_SESS_TIMEOUT_NORMAL; valId <= AR_SESS_TIMEOUT_XLONG; ++valId)
165                        {
166                                ARZeroMemory(&val);
167                                nResult = ARGetSessionConfiguration(&this->arControl, valId, &val, &status);
168
169                                // validate result
170                                if (nResult != AR_RETURN_OK) continue;  // ok, if this fails, dont bother .. next one
171                                if (val.dataType != AR_DATA_TYPE_INTEGER) continue;
172                                if (val.u.intVal > this->appConfig.apiTimeout) continue;
173
174                                // setup value
175                                val.dataType = AR_DATA_TYPE_INTEGER;
176                                val.u.intVal = this->appConfig.apiTimeout;
177
178                                // now configure session
179                                nResult = ARSetSessionConfiguration(&this->arControl, valId, &val, &status);
180                                if (nResult != AR_RETURN_OK)
181                                {
182                                        cout << "Setting session timeout failed: " << BuildMessageAndFreeStatus(status);
183                                }
184                        }
185                }
186
187                if(nResult == AR_RETURN_OK)
188                {
189                        ARBoolean isAdmin, isSubadmin, hasCustomize;
190                        nResult = ARVerifyUser(&this->arControl, &isAdmin, &isSubadmin, &hasCustomize, &status);
191                       
192                        if (nResult != AR_RETURN_OK)
193                        {
194                                throw(AppException(BuildMessageAndFreeStatus(status), "undefined", "ARSystem"));
195                        }
196                        FreeARStatusList(&status, false);
197
198                        serverInfoList.LoadAndGetValue(AR_SERVER_INFO_HOSTNAME, StoreTo(this->srvHostName));
199                        serverInfoList.LoadAndGetValue(AR_SERVER_INFO_FULL_HOSTNAME, StoreTo(this->srvFullHostName));
200                        serverInfoList.LoadAndGetValue(AR_SERVER_INFO_VERSION, StoreTo(this->arServerVersion));
201
202                        ParseVersionString(this->arServerVersion);
203
204#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
205                        if (CompareServerVersion(7,6,4) >= 0)
206                                serverInfoList.LoadAndGetValue(AR_SERVER_INFO_OVERLAY_MODE, StoreTo(this->overlayMode));
207#endif
208                        cout << "User '" << this->arControl.user <<"' connected to server " << srvFullHostName << endl;
209
210                        // the most ARGetMultiple... calls aren't supported below ARServer 6.3 so it's better to
211                        // switch to slow object loadinig automatically
212                        if (CompareServerVersion(6,3) < 0)
213                                appConfig.slowObjectLoading = true;
214
215                        blackList.LoadFromServer(appConfig.blackList);
216                }
217        }
218
219        FreeARStatusList(&status, false);
220        return nResult;
221}
222
223int CARInside::Terminate(void)
224{
225        ARStatusList status;
226        ARZeroMemory(&status);
227
228        ARTermination(&this->arControl, &status);
229       
230        FreeARStatusList(&status, false);
231        return 0;
232}
233
234bool CARInside::FileExists(string fName)
235{
236        bool result = FileSystemUtil::FileExistsAndReadable(fName);
237        if (result)
238                cout << fName << " exists" << endl;
239        return result;
240}
241
242
243void CARInside::Prepare(void)
244{       
245        CDocMain *docMain = new CDocMain();
246
247        if( docMain->Index() == 1)
248        {
249                InitFileNamingStrategy();
250                if (appConfig.bGZCompression)
251                        WriteHTAccess();
252        }
253
254        delete docMain;
255}
256
257bool CARInside::FieldreferenceExists(int schemaInsideId, int fieldInsideId, const CRefItem &refItem)
258{
259        CARField fld(schemaInsideId, fieldInsideId);
260        if (!fld.Exists()) return false;
261
262        return fld.ReferenceExists(refItem);
263}
264
265void CARInside::LoadServerObjects(int nMode)
266{
267        CAppTimer mTimer;
268        mTimer.StartTimer();
269
270        if(nMode==1)
271        {
272                this->LoadFromFile();
273        }
274        else
275        {
276                this->LoadFromServer();
277        }
278        mTimer.EndTimer();
279        this->nDurationLoad = mTimer.GetDuration();
280}
281
282void CARInside::LoadFromFile(void)
283{
284        try
285        {
286                cout << endl << "Loading objects from file '" << appConfig.objListXML << "'" << endl;
287
288                ARStatusList status;
289                ARZeroMemory(&status);
290
291                ARXMLInputDoc xmlInputDoc;
292                xmlInputDoc.docType = AR_XML_DOC_FILE_NAME;
293                xmlInputDoc.u.fileName = (char*)appConfig.objListXML.c_str();
294
295                ARXMLParsedStream parsedStream;
296                ARStructItemList parsedObjects;
297                unsigned int xmlDocVersion = 0;
298
299                if(ARParseXMLDocument(&this->arControl, 
300                        &xmlInputDoc,
301                        NULL,
302                        &parsedStream,
303                        &parsedObjects,
304                        NULL,
305                        &status) == AR_RETURN_OK)
306                {                       
307                        cout << parsedObjects.numItems << " items loaded." << endl;
308
309                        unsigned int schemaCount = 0;
310                        unsigned int imagesCount = 0;
311                        unsigned int activelinkCount = 0;
312                        unsigned int filterCount = 0;
313                        unsigned int escalationCount = 0;
314                        unsigned int containerCount = 0;
315                        unsigned int menuCount = 0;
316
317                        for (unsigned int i=0; i < parsedObjects.numItems; ++i)
318                        {
319                                switch (parsedObjects.structItemList[i].type)
320                                {
321                                case AR_STRUCT_ITEM_XML_SCHEMA:
322                                        ++schemaCount;
323                                        break;
324                                case AR_STRUCT_ITEM_XML_ACTIVE_LINK:
325                                        ++activelinkCount;
326                                        break;
327                                case AR_STRUCT_ITEM_XML_FILTER:
328                                        ++filterCount;
329                                        break;
330                                case AR_STRUCT_ITEM_XML_ESCALATION:
331                                        ++escalationCount;
332                                        break;
333                                case AR_STRUCT_ITEM_XML_CONTAINER:
334                                        ++containerCount;
335                                        break;
336                                case AR_STRUCT_ITEM_XML_CHAR_MENU:
337                                        ++menuCount;
338                                        break;
339#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
340                                case AR_STRUCT_ITEM_XML_IMAGE:
341                                        ++imagesCount; 
342                                        break;
343#endif
344                                }
345                        }
346
347                        if (schemaCount > 0) schemaList.Reserve(schemaCount);
348                        if (activelinkCount > 0) alList.Reserve(activelinkCount);
349                        if (filterCount > 0) filterList.Reserve(filterCount);
350                        if (escalationCount > 0) escalationList.Reserve(escalationCount);
351                        if (containerCount > 0) containerList.Reserve(containerCount);
352                        if (menuCount > 0) menuList.Reserve(menuCount);
353#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
354                        if (imagesCount > 0) imageList.Reserve(imagesCount);
355#endif
356
357                        for(unsigned int i=0; i< parsedObjects.numItems; i++)
358                        {
359                                switch(parsedObjects.structItemList[i].type)
360                                {                                               
361                                case AR_STRUCT_ITEM_XML_FILTER:
362                                        {
363                                                LOG << "Loading Filter: " << parsedObjects.structItemList[i].name; 
364
365                                                int objInsideId = filterList.AddFilterFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
366
367                                                if (objInsideId > -1)
368                                                {
369                                                        ParseVersionString(xmlDocVersion);
370                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
371                                                }
372                                        }
373                                        break;
374                                case AR_STRUCT_ITEM_XML_SCHEMA:
375                                        {
376                                                LOG << "Loading Form: " << parsedObjects.structItemList[i].name;
377
378                                                int objInsideId = schemaList.AddSchemaFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
379
380                                                if (objInsideId > -1)
381                                                {
382                                                        ParseVersionString(xmlDocVersion);
383                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
384                                                }
385                                        }
386                                        break;                                 
387                                case AR_STRUCT_ITEM_XML_ACTIVE_LINK:
388                                        {
389                                                LOG << "Loading ActiveLink: " << parsedObjects.structItemList[i].name; 
390
391                                                int objInsideId = alList.AddActiveLinkFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
392
393                                                if (objInsideId > -1)
394                                                {
395                                                        ParseVersionString(xmlDocVersion);
396                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
397                                                }
398                                        }
399                                        break;
400                                case AR_STRUCT_ITEM_XML_CHAR_MENU:
401                                        {
402                                                LOG << "Loading CharMenu: " << parsedObjects.structItemList[i].name; 
403
404                                                int objInsideId = menuList.AddMenuFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
405
406                                                if (objInsideId > -1)
407                                                {
408                                                        ParseVersionString(xmlDocVersion);
409                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
410                                                }
411                                        }
412                                        break;
413                                case AR_STRUCT_ITEM_XML_ESCALATION:
414                                        {
415                                                LOG << "Loading Escalation: " << parsedObjects.structItemList[i].name; 
416
417                                                int objInsideId = escalationList.AddEscalationFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
418
419                                                if (objInsideId > -1)
420                                                {
421                                                        ParseVersionString(xmlDocVersion);
422                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
423                                                }
424                                        }
425                                        break;
426                                case AR_STRUCT_ITEM_XML_CONTAINER:
427                                        {
428                                                LOG << "Loading Container: " << parsedObjects.structItemList[i].name; 
429
430                                                int objInsideId = containerList.AddContainerFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
431
432                                                if (objInsideId > -1)
433                                                {
434                                                        ParseVersionString(xmlDocVersion);
435                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
436                                                }
437                                        }
438                                        break;
439#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
440                                case AR_STRUCT_ITEM_XML_IMAGE:
441                                        {
442                                                LOG << "Loading Image: " << parsedObjects.structItemList[i].name;
443                                               
444                                                int imageInsideId = imageList.AddImageFromXML(parsedStream, parsedObjects.structItemList[i].name);
445                                               
446                                                // dont know why bmc has decided to remove the arDocVersion parameter from the
447                                                // ARGetImageFromXML api call. Now in case the xml-file contains only images we
448                                                // dont have a version at all. So we set it to version 7.5 by default. if other
449                                                // objects are present they will overwrite this version if it is a 7.5+ version.
450                                                ParseVersionString(AR_XML_VERSION_750);
451
452                                                if (imageInsideId > -1)
453                                                {
454                                                        LOG << " (InsideID: " << imageInsideId << ") [OK]" << endl;
455                                                }
456                                        }
457                                        break;
458#endif
459#if _DEBUG
460                                default:
461                                        cout << "Unused object type: [" << parsedObjects.structItemList[i].type << "] " << parsedObjects.structItemList[i].name << endl;
462                                        break;
463#endif
464                                }       
465                        }               
466                       
467                        schemaList.Sort();
468                        alList.Sort();
469                        filterList.Sort();
470                        escalationList.Sort();
471                        containerList.Sort();
472                        menuList.Sort();
473#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
474                        imageList.Sort();
475#endif
476                }
477                else
478                {
479                        cout << "An error occured parsing the xml document '" << appConfig.objListXML << "'" << endl;
480                        cout << BuildMessageAndFreeStatus(status);
481                }
482                if (!arServerVersion.empty())
483                        cout << "server version: " << arServerVersion << endl;
484
485                FreeARXMLParsedStream(&parsedStream, false);
486                FreeARStatusList(&status, false);
487        } 
488        catch (...)
489        { 
490                cerr << "EXCEPTION loading server objects from xml file." << endl; 
491        }
492}
493
494void CARInside::LoadFromServer(void)
495{
496        cout << endl << "Loading objects from server '" << appConfig.serverName << "'" << endl;
497        cout << "server version: " << arServerVersion << endl;
498
499        if (appConfig.slowObjectLoading)
500        {
501                cout << "NOTE: Fast object loading disabled!" << endl;
502        }
503
504        //LoadServerInfoList   
505        if(appConfig.bLoadServerInfoList)
506        {
507                cout << "Start loading Server Information:" << endl;
508                serverInfoList.Load();
509                cout << serverInfoList.GetCount() << " server settings loaded" << endl;
510        }
511        else
512                cout << endl << "Loading Server Informations [SKIPPED]" << endl;
513
514        //LoadUserList
515        if(appConfig.bLoadUserList)
516        {
517                cout << endl << "Start loading Users:" << endl;         
518                userList.LoadFromServer();
519                cout << userList.GetCount() << " Users loaded" << endl;
520        }
521        else
522                cout << endl << "Loading Users [SKIPPED]" << endl;
523
524
525        //LoadGroupList
526        if(appConfig.bLoadGroupList)
527        {
528                cout << endl << "Start loading Groups:" << endl;               
529                groupList.LoadFromServer();
530                cout << groupList.GetCount() << " Groups loaded" << endl;
531        }
532        else
533                cout << endl << "Loading Groups [SKIPPED]" << endl;
534
535        //LoadRoleList
536        if(appConfig.bLoadRoleList)
537        {
538                cout << endl << "Start loading Roles:" << endl;         
539                roleList.LoadFromServer();
540                cout << (unsigned int)roleList.GetCount() << " Roles loaded" << endl;
541        }
542        else
543                cout << endl << "Loading Roles [SKIPPED]" << endl;
544
545        SetupOverlaySupport();
546
547        //ActiveLinks           
548        cout << endl << "Start loading Active Links:" << endl;
549        int nResult = LoadActiveLinks();
550        cout << nResult << " Active Links loaded" << endl;
551
552
553        //Filters       
554        cout << endl << "Start loading Filters:" << endl;
555        nResult = LoadFilters();
556        cout << nResult << " Filters loaded" << endl;
557
558        //Container     
559        cout << endl << "Start loading Containers:" << endl;
560        nResult = LoadContainer();
561        cout << nResult << " Containers loaded" << endl;
562
563        //Escalations   
564        cout << endl << "Start loading Escalations:" << endl;
565        nResult = LoadEscalations();
566        cout << nResult << " Escalations loaded" << endl;
567
568        //CharMenus     
569        cout << endl << "Start loading Menus:" << endl;
570        nResult = LoadCharMenus();
571        cout << nResult << " Menus loaded" << endl;
572
573        //Images
574#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
575        if (CompareServerVersion(7,5) >= 0)
576        {
577                cout << endl << "Start loading Images:" << endl;
578                nResult = LoadImages();
579                cout << nResult << " Images loaded" << endl;
580        }
581#endif
582
583        //Load schemas
584        cout << endl << "Start loading Forms:" << endl;
585        nResult = LoadForms();
586        cout << nResult << " Forms loaded" << endl << endl;
587}
588
589int CARInside::LoadForms()
590{
591        try
592        {
593                schemaList.LoadFromServer();
594                schemaList.Sort();
595        }
596        catch(exception& e)
597        {
598                cout << "EXCEPTION loading Forms: " << e.what() << endl;
599        }
600
601        return schemaList.GetCount();
602}
603
604int CARInside::LoadContainer(void)
605{
606        try
607        {
608                containerList.LoadFromServer();
609                containerList.Sort();           
610        }
611        catch(exception& e)
612        {
613                cout << "EXCEPTION loading Container: " << e.what() << endl;
614        }
615
616        return containerList.GetCount();
617}
618
619int CARInside::LoadCharMenus(void)
620{
621        try
622        {
623                menuList.LoadFromServer();
624                menuList.Sort();
625        }
626        catch(exception& e)
627        {
628                cout << "EXCEPTION loading Menus: " << e.what() << endl;
629        }
630
631        return menuList.GetCount();
632}
633
634int CARInside::LoadEscalations(void)
635{
636        try
637        {
638                escalationList.LoadFromServer();
639                escalationList.Sort();
640        }
641        catch(exception& e)
642        {
643                cout << "EXCEPTION loading Escalations: " << e.what() << endl;
644        }
645
646        return escalationList.GetCount();
647}
648
649int CARInside::LoadFilters(void)
650{
651        try
652        {
653                filterList.LoadFromServer();
654                filterList.Sort();
655        }
656        catch(exception& e)
657        {
658                cout << "EXCEPTION loading Filters: " << e.what() << endl;
659        }
660
661        return filterList.GetCount();
662}
663
664int CARInside::LoadActiveLinks(void)
665{
666        try
667        {
668                alList.LoadFromServer();
669                alList.Sort();
670        }
671        catch(exception& e)
672        {
673                cout << "EXCEPTION loading ActiveLinks: " << e.what() << endl;
674        }
675        return alList.GetCount();
676}
677
678void CARInside::Documentation(void)
679{       
680        CAppTimer mTimer;
681        mTimer.StartTimer();
682
683        string strValue = objectNameFirstCharLetters; // "abcdefghijklmnopqrstuvwxyz0123456789#";
684        CDocMain *docMain = new CDocMain();
685
686        //Server information
687        docMain->ServerInfoList();
688
689        CDocSummaryInfo indexSummary(*this, "");        // this is the object for the summary start page (it's written at the end of this function)
690
691        //ContainerList
692        indexSummary.alguideCount = docMain->ContainerList(ARCON_GUIDE, "ContainerList (ActiveLinkGuide)");
693        indexSummary.applicationCount = docMain->ContainerList(ARCON_APP, "ContainerList (Application)");
694        indexSummary.packlistCount = docMain->ContainerList(ARCON_PACK, "ContainerList (PackingList)");
695        indexSummary.fltguideCount = docMain->ContainerList(ARCON_FILTER_GUIDE, "ContainerList (FilterGuide)");
696        indexSummary.webserviceCount = docMain->ContainerList(ARCON_WEBSERVICE, "ContainerList (Webservice)");
697
698        //Application Details
699        int nTmpCnt = 1;
700
701        //Create documentation here to fill objects applicationName reference information       
702        cout << "Starting Container Documentation" << endl;
703
704        unsigned int cntCount = this->containerList.GetCount();
705        for ( unsigned int cntIndex = 0; cntIndex < cntCount; ++cntIndex )
706        {
707                CARContainer cont(cntIndex);
708
709                switch(cont.GetType())
710                {
711                case ARCON_APP:
712                        {
713                                LOG << "Application [" << (cntIndex + 1) << "-" << cntCount << "] '" << cont.GetName() << "': ";
714                                CDocApplicationDetails appDetails(cont);
715                                appDetails.Documentation();
716                        }
717                        break;
718                default:
719                        {
720                                // TODO: is this output really correct? All other container types are documented and LOGged within the next loop!
721                                LOG << "Container [" << (cntIndex + 1) << "-" << cntCount << "] '" << cont.GetName() << "' [OK]" << endl;
722                        }
723                        break;
724                }
725
726                nTmpCnt++;
727        }
728
729        unsigned int tmpCount = this->containerList.GetCount();
730        for ( unsigned int cntIndex = 0; cntIndex < tmpCount; ++cntIndex )
731        {
732                CARContainer cont(cntIndex);
733                switch(cont.GetType())
734                {
735                case ARCON_WEBSERVICE:
736                        {
737                                LOG << "Webservice [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
738                                CDocWebserviceDetails wsDetails(cont);
739                                wsDetails.Documentation();
740                        }
741                        break;
742                case ARCON_GUIDE:
743                        {
744                                LOG << "ActiveLinkGuide [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
745                                CDocAlGuideDetails guideDetails(cont);
746                                guideDetails.Documentation();
747                        }
748                        break;
749                case ARCON_FILTER_GUIDE:
750                        {
751                                LOG << "FilterGuide [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
752                                CDocFilterGuideDetails fltGuideDetails(cont);
753                                fltGuideDetails.Documentation();
754                        }
755                        break;
756                case ARCON_PACK:
757                        {
758                                LOG << "PackingList [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
759                                CDocPacklistDetails packDetails(cont);
760                                packDetails.Documentation();
761                        }
762                        break;
763                case ARCON_APP:
764                        {
765                                LOG << "Application [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "' [OK]" << endl;
766                        }
767                        break;
768                }
769
770                nTmpCnt++;
771        }
772
773
774        //ActiveLink List
775        indexSummary.activelinkCount = docMain->ActiveLinkList();
776        docMain->ActiveLinkActionList();
777
778        //ActiveLink Details
779        tmpCount = alList.GetCount();
780        cout << "Starting ActiveLink Documentation" << endl;
781        for (unsigned int actlinkIndex = 0; actlinkIndex < tmpCount; ++actlinkIndex)
782        {       
783                LOG << "ActiveLink [" << actlinkIndex << "-" << nTmpCnt << "] '" << alList.ActiveLinkGetName(actlinkIndex) << "': ";
784                CDocAlDetails alDetails(actlinkIndex);
785                alDetails.Documentation();
786        }
787
788
789        //Filter List
790        indexSummary.filterCount = docMain->FilterList();
791        docMain->FilterActionList();
792        docMain->FilterErrorHandlers();
793
794        //Filter Details
795        tmpCount = filterList.GetCount();
796        cout << "Starting Filter Documentation" << endl;
797        for (unsigned int filterIndex = 0; filterIndex < tmpCount; ++filterIndex)
798        {
799                LOG << "Filter [" << filterIndex << "-" << tmpCount << "] '" << filterList.FilterGetName(filterIndex) << "': ";
800                CDocFilterDetails filterDetails(filterIndex);
801                filterDetails.Documentation();
802        }
803
804
805        //Escalation List
806        indexSummary.escalationCount = docMain->EscalationList();
807        docMain->EscalationActionList();
808
809        //Escalation Details
810        tmpCount = escalationList.GetCount();
811        cout << "Starting Escalation Documentation" << endl;
812        for (unsigned int escalIndex = 0; escalIndex < tmpCount; ++escalIndex)
813        {
814                LOG << "Escalation [" << escalIndex << "-" << tmpCount << "] '" << escalationList.EscalationGetName(escalIndex) << "': ";
815                CDocEscalationDetails escalDetails(escalIndex);
816                escalDetails.Documentation();
817        }
818
819
820        //CharMenus
821        indexSummary.menuCount = docMain->CharMenuList();
822
823        // Char Menu Details
824        tmpCount = menuList.GetCount();
825        cout << "Starting Menu Documentation" << endl;
826        for (unsigned int menuIndex = 0; menuIndex < tmpCount; ++menuIndex)
827        {
828                LOG << "Menu [" << menuIndex << "-" << tmpCount << "] '" << menuList.MenuGetName(menuIndex) << "': ";
829                CDocCharMenuDetails menuDetails(menuIndex);
830                menuDetails.Documentation();
831        }
832
833
834        //Schema List
835        indexSummary.schemaCount = docMain->SchemaList();
836
837        //Schema and field Details
838        nTmpCnt=1;
839        unsigned int schemaCount = schemaList.GetCount();
840        cout << "Starting Schema Documentation" << endl;
841        for (unsigned int schemaIndex = 0; schemaIndex < schemaCount; ++schemaIndex)
842        {
843                int rootLevel = 2;
844                CARSchema schema(schemaIndex);
845
846                LOG << "Schema [" << (schemaIndex + 1) << "-" << schemaCount << "] '" << schema.GetName() << "': ";
847                CDocSchemaDetails *schemaDetails = new CDocSchemaDetails(schemaIndex, rootLevel);
848                schemaDetails->Documentation();
849                delete schemaDetails;
850
851
852                //VuiDetails
853                LOG << "VuiDetails Schema '" << schema.GetName() << "'" << endl;
854                unsigned int objCount = schema.GetVUIs()->GetCount();
855                for (unsigned int vuiIndex = 0; vuiIndex < objCount; ++vuiIndex)
856                {
857                        CARVui vui(schema.GetInsideId(), 0, vuiIndex);
858
859                        LOG << "SchemaView '" << vui.GetName() << "': ";
860                        CDocVuiDetails *vuiDetails = new CDocVuiDetails(schema.GetInsideId(), vui, rootLevel);
861                        vuiDetails->Documentation();
862                        delete vuiDetails;
863                }
864
865                //FieldDetails
866                LOG << "FieldDetails Schema '" << schema.GetName() << "'" << endl;             
867                objCount = schema.GetFields()->GetCount();
868                for (unsigned int fieldIndex = 0; fieldIndex < objCount; ++fieldIndex)
869                {       
870                        CARField field(schema.GetInsideId(), 0, fieldIndex);
871                        CDocFieldDetails *fieldDetails = new CDocFieldDetails(schema.GetInsideId(), field, rootLevel);
872                        fieldDetails->Documentation();
873                        delete fieldDetails;
874                }
875
876                nTmpCnt++;
877        }
878
879#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
880
881        // Image
882        {
883                CDocImageOverview imageOverview;
884                indexSummary.imageCount = imageOverview.Build();
885        }
886
887        // Image Details
888        tmpCount = imageList.GetCount();
889        cout << "Starting Image Documentation" << endl;
890        for (unsigned int imgIndex = 0; imgIndex < tmpCount; ++imgIndex)
891        {
892                LOG << "Image [" << imgIndex << "-" << nTmpCnt << "] '" << imageList.ImageGetName(imgIndex) << "': ";
893
894                CDocImageDetails imgDetails(imgIndex);
895                imgDetails.Documentation();
896        }
897#endif
898
899        //GlobalFieldList
900        docMain->GlobalFieldList();     
901
902        //MessageList
903        docMain->MessageList(); 
904
905        //NotificationList
906        docMain->NotificationList();
907
908        //Analyzer
909        CDocAnalyzer *analyzer = new CDocAnalyzer();
910        analyzer->Documentation();
911        delete analyzer;
912
913        //Validation
914        CDocValidator *validator = new CDocValidator();
915        validator->Main();
916        delete validator;
917
918        {
919                CDocCustomWorkflow customWF;
920                customWF.Documentation();
921        }
922
923
924        //Group List
925        docMain->GroupList();
926
927        //Group Details
928        cout << "Starting Group Documentation" << endl;
929
930        tmpCount = groupList.GetCount();
931        for (unsigned int groupIndex = 0; groupIndex < tmpCount; ++groupIndex)
932        {
933                CARGroup grp(groupIndex);
934
935                LOG << "Group [" << (groupIndex + 1) << "-" << tmpCount << "] '" << grp.GetName() << "': ";
936                CDocGroupDetails grpDetails(grp);
937                grpDetails.Documentation();
938        }
939
940
941        //Role List
942        docMain->RoleList();
943
944        //Role Details
945        cout << "Starting Role Documentation" << endl;
946
947        tmpCount = roleList.GetCount();
948        for (unsigned int roleIndex = 0; roleIndex < tmpCount; ++roleIndex)
949        {
950                CARRole role(roleIndex);
951
952                LOG << "Role [" << (roleIndex + 1) << "-" << tmpCount << "] '" << role.GetName() << "': ";
953                CDocRoleDetails roleDetails(role);
954                roleDetails.Documentation();
955        }
956
957
958        // user count per first char
959        vector<int> usrObjCount; usrObjCount.resize(38);
960
961        //Userlists
962        docMain->UserList("*", usrObjCount);
963        for (unsigned int i = 0; i < strValue.size(); ++i)
964        {               
965                docMain->UserList(std::string(1, strValue.at(i)), usrObjCount);
966        }       
967
968        //User Details
969        cout << "Starting User Documentation" << endl;
970
971        tmpCount = userList.GetCount();
972        for (unsigned int userIndex = 0; userIndex < tmpCount; ++userIndex)
973        {
974                CARUser user(userIndex);
975
976                LOG << "User [" << (userIndex + 1) << "-" << tmpCount << "] '" << user.GetName() << "': ";
977               
978                CDocUserDetails userDetails(user);
979                userDetails.Documentation();
980        }
981
982        mTimer.EndTimer();
983        this->nDurationDocumentation = mTimer.GetDuration();
984
985        indexSummary.Documentation();
986
987        delete docMain;
988}
989
990string CARInside::GetFieldEnumValue(int schemaInsideId, int fieldInsideId, int enumPosition)
991{
992        CARField field(schemaInsideId, fieldInsideId);
993        if (field.Exists())
994        {
995                if(field.GetDataType() == AR_DATA_TYPE_ENUM)
996                {
997                        const ARFieldLimitStruct& limits = field.GetLimits();
998                        switch(limits.u.enumLimits.listStyle)
999                        {
1000                        case AR_ENUM_STYLE_REGULAR:
1001                                if (static_cast<unsigned int>(enumPosition) < limits.u.enumLimits.u.regularList.numItems)
1002                                        return limits.u.enumLimits.u.regularList.nameList[enumPosition];
1003                                break;
1004                        case AR_ENUM_STYLE_CUSTOM:
1005                                for (unsigned int i=0; i < limits.u.enumLimits.u.customList.numItems; i++) { 
1006                                        if (limits.u.enumLimits.u.customList.enumItemList[i].itemNumber == enumPosition) 
1007                                                return limits.u.enumLimits.u.customList.enumItemList[i].itemName; 
1008                                } 
1009                                break;
1010                        case AR_ENUM_STYLE_QUERY:
1011                                return "QUERY";
1012                        }                                               
1013                }
1014        }
1015        return "";
1016}
1017
1018string CARInside::LinkToVui(int schemaInsideId, int vuiInsideId, int fromRootLevel)
1019{
1020        CARVui vui(schemaInsideId, vuiInsideId);
1021        if (vui.Exists())
1022        {
1023                return URLLink(vui, fromRootLevel);
1024        }
1025        return "";
1026}
1027
1028string CARInside::LinkToField(const string& schemaName, int fieldInsideId, int fromRootLevel)
1029{       
1030        CARSchema schema(schemaName);
1031        return LinkToField(schema.GetInsideId(), fieldInsideId, fromRootLevel);
1032}
1033
1034string CARInside::LinkToField(Context &context, int fieldInsideId)
1035{
1036        return LinkToField(context.getCurrentSchemaId(), fieldInsideId, context.getRootLevel());
1037}
1038
1039string CARInside::LinkToField(LookupFormContext &lookupContext, int fieldInsideId)
1040{
1041        return LinkToField(lookupContext.getLookupSchemaId(), fieldInsideId, lookupContext.getRootLevel());
1042}
1043
1044string CARInside::LinkToField(int schemaInsideId, int fieldInsideId, const string& linkText, int fromRootLevel)
1045{       
1046        CARField field(schemaInsideId, fieldInsideId);
1047        if (field.Exists())
1048        {
1049                return URLLink(linkText, field, fromRootLevel);
1050        }
1051
1052        //Field has not been found
1053        stringstream tmp;
1054
1055        if(fieldInsideId > 0 && schemaInsideId > -1) //OpenWindow uses 0 what is no valid field
1056        {
1057                ObjNotFound notFound(tmp);
1058                notFound << fieldInsideId;
1059                notFound.End();
1060        }
1061        else
1062        {
1063                tmp << fieldInsideId;
1064        }
1065
1066        return tmp.str();
1067}
1068
1069string CARInside::LinkToField(int schemaInsideId, int fieldInsideId, int fromRootLevel)
1070{
1071        return LinkToField(schemaInsideId, fieldInsideId, "", fromRootLevel);
1072}
1073
1074// TODO: maybe change callers to LinkToField and remove this function completely
1075string CARInside::LinkToMenuField(int schemaInsideId, int fieldInsideId, int fromRootLevel)
1076{
1077        return LinkToField(schemaInsideId, fieldInsideId, fromRootLevel);
1078}
1079
1080string CARInside::LinkToSchemaTypeList(int schemaType, int rootLevel)
1081{
1082        unsigned int page = PAGE_OVERVIEW;
1083
1084        switch (schemaType)
1085        {
1086                case AR_SCHEMA_REGULAR: page = PAGE_SCHEMA_REGULAR; break;
1087                case AR_SCHEMA_JOIN: page = PAGE_SCHEMA_JOIN; break;
1088                case AR_SCHEMA_VIEW: page = PAGE_SCHEMA_VIEW; break;
1089                case AR_SCHEMA_DIALOG: page = PAGE_SCHEMA_DIALOG; break;
1090                case AR_SCHEMA_VENDOR: page = PAGE_SCHEMA_VENDOR; break;
1091                case AR_SCHEMA_AUDIT: page = PAGE_SCHEMA_AUDIT; break;
1092                case AR_SCHEMA_ARCHIVE: page = PAGE_SCHEMA_ARCHIVE; break;
1093        }
1094
1095        return URLLink(CAREnum::SchemaType(schemaType), page, rootLevel);
1096}
1097
1098// TODO: add a function with parameter CARSchema instead of schemaInsideId to pass in the object directly
1099string CARInside::LinkToSchemaIndex(string indexName, int schemaInsideId, int fromRootLevel)
1100{
1101        CARSchema schema(schemaInsideId);
1102        CPageParams file(PAGE_SCHEMA_INDEXES, &schema);
1103        return URLLink(indexName, file, fromRootLevel);
1104}
1105
1106string CARInside::LinkToSchema(int insideId, int fromRootLevel)
1107{
1108        return LinkToSchema(insideId, EmptyValue, fromRootLevel);
1109}
1110
1111string CARInside::LinkToSchema(const string& schemaName, int fromRootLevel)
1112{
1113        CARSchema schema(schemaName);
1114        if(schema.Exists())
1115        {
1116                return URLLink(schema, fromRootLevel);
1117        }
1118        return schemaName;
1119}
1120
1121string CARInside::LinkToSchema(int schemaInsideId, const string &nameToUseIfSchemaNotExists, int fromRootLevel)
1122{
1123        CARSchema schema(schemaInsideId);
1124        if (schema.Exists())
1125        {
1126                return URLLink(schema, fromRootLevel);
1127        }
1128        return nameToUseIfSchemaNotExists;
1129}
1130
1131int CARInside::SchemaGetInsideId(string searchObjName)
1132{
1133        CARSchema schema(searchObjName);
1134        if (schema.Exists())
1135        {
1136                return schema.GetInsideId();
1137        }
1138        return -1;
1139}
1140
1141string CARInside::LinkToUser(string loginName, int rootLevel)
1142{
1143        CARUser user(loginName);
1144
1145        if (user.Exists())
1146                return URLLink(loginName, CPageParams(PAGE_DETAILS, &user), rootLevel);
1147
1148        return loginName;
1149}
1150
1151bool CARInside::ValidateGroup(const string& appRefName, int permissionId)
1152{
1153        if(permissionId >= 0)
1154        {
1155                return true;
1156        }
1157        else
1158        {
1159                CARRole role(permissionId, appRefName);
1160
1161                if (role.Exists())
1162                {
1163                        return true;
1164                }
1165        }
1166
1167        return false;
1168}
1169
1170string CARInside::LinkToGroup(const string& appRefName, int permissionId, int rootLevel)
1171{       
1172        if(permissionId >= 0)
1173        {
1174                CARGroup group(-1, permissionId);
1175                if (group.Exists())
1176                {
1177                        return URLLink(group, rootLevel);
1178                }               
1179        }
1180        else
1181        {
1182                if(!appRefName.empty())
1183                {
1184                        CARRole role(permissionId, appRefName);
1185
1186                        if(role.Exists())
1187                        {
1188                                return URLLink(role, rootLevel);
1189                        }
1190                }
1191        }
1192
1193        stringstream strmTmp;
1194        strmTmp << permissionId;
1195        return strmTmp.str();
1196}
1197
1198string CARInside::LinkToAl(const string& alName, int fromRootLevel)
1199{
1200        CARActiveLink al(alName);
1201        if (!al.Exists())
1202                return alName;
1203
1204        return URLLink(al, fromRootLevel);
1205}
1206
1207string CARInside::LinkToAl(int alInsideId, int rootLevel)
1208{
1209        CARActiveLink al(alInsideId);
1210
1211        if (al.Exists())
1212                return URLLink(al, rootLevel);
1213
1214        return EmptyValue;
1215}
1216
1217string CARInside::LinkToFilter(string filterName, int fromRootLevel)
1218{
1219        if (filterName.empty()) return filterName;
1220
1221        int fltInsideId = filterList.Find(filterName.c_str());
1222        if (fltInsideId > -1)
1223        {
1224                CARFilter flt(fltInsideId);
1225                return URLLink(flt, fromRootLevel);
1226        }
1227        return filterName;
1228}
1229
1230string CARInside::LinkToEscalation(const string& escalationName, int fromRootLevel)
1231{
1232        CAREscalation escal(escalationName);
1233        if (escal.Exists())
1234        {
1235                return URLLink(escal, fromRootLevel);
1236        }
1237        return escalationName;
1238}
1239
1240string CARInside::LinkToEscalation(const CRefItem& refItem, int fromRootLevel)
1241{
1242        CAREscalation escal(refItem.GetObjectId());
1243        if (escal.Exists())
1244        {
1245                return URLLink(escal, fromRootLevel);
1246        }
1247        return EmptyValue;
1248}
1249
1250string CARInside::LinkToContainer(string containerName, int fromRootLevel)
1251{
1252        CARContainer cnt(containerName);
1253        if (cnt.Exists())
1254        {
1255                return URLLink(cnt, fromRootLevel);
1256        }
1257        return containerName;
1258}
1259
1260string CARInside::LinkToContainer(const CRefItem& refItem, int rootLevel)
1261{
1262        CARContainer cnt(refItem.GetObjectId());
1263        if (cnt.Exists())
1264        {
1265                return URLLink(cnt, rootLevel);
1266        }
1267        return EmptyValue;
1268}
1269
1270string CARInside::LinkToServerInfo(const std::string &srvName, int rootLevel)
1271{               
1272        string result;
1273
1274        if(srvName.empty())
1275        {
1276                return URLLink(appConfig.serverName, PAGE_SERVER_INFO, rootLevel);
1277        }
1278        else if(srvName.compare(AR_CURRENT_SERVER_TAG)==0 || srvName.compare(AR_CURRENT_SCREEN_TAG)==0)
1279        {
1280                return URLLink(appConfig.serverName, PAGE_SERVER_INFO, rootLevel);
1281        }
1282        else
1283        {
1284                return URLLink(srvName, PAGE_SERVER_INFO, rootLevel);
1285        }
1286
1287        return result;
1288}
1289
1290string CARInside::LinkToServerInfo(Context &context, const std::string &srvName)
1291{
1292        return LinkToServerInfo(srvName, context.getRootLevel());
1293}
1294
1295void CARInside::AddFieldReference(int schemaId, int fieldId, const CRefItem& ref)
1296{
1297        if (ref.GetMessageId() == -1) return; // if no message id is specified, dont create a reference
1298
1299        CARHandle<> hObj(ref);
1300        if (appConfig.bOverlaySupport && hObj.Exists() && !IsVisibleObject(*hObj))
1301                return;
1302
1303        CARSchema schema(schemaId);
1304        CARField fld(schemaId, fieldId);
1305
1306        if (fld.Exists())
1307        {
1308                if (!fld.ReferenceExists(ref))
1309                        fld.AddReference(ref);
1310        }
1311        else if (schema.Exists())
1312        {
1313                schema.AddMissingFieldReference(fieldId, ref);
1314        }
1315        // TODO: create a list of missing schemas
1316        //else
1317        //{
1318        //      LOG << "Missing Schema!" << endl;
1319        //}
1320}
1321
1322void CARInside::AddMenuReference(const string& menuName, const CRefItem &ref)
1323{
1324        if (menuName == "$NULL$") return;
1325
1326        CARCharMenu menu(menuName);
1327
1328        if (menu.Exists())
1329        {
1330                // if the menu was found add the referece to it
1331                if (!menu.ReferenceExists(ref))
1332                        menu.AddReference(ref);
1333        }
1334        else
1335        {
1336                // if the menu is missing, add the name to the missing menus map and append the reference to it
1337                if (missingMenuReferences.find(menuName) != missingMenuReferences.end())
1338                {
1339                        missingMenuReferences.insert(pair<string, vector<CRefItem> >(menuName, vector<CRefItem>()));
1340                }
1341
1342                CARCharMenu::ReferenceList::iterator curIt = missingMenuReferences[menuName].begin();
1343                CARCharMenu::ReferenceList::iterator endIt = missingMenuReferences[menuName].end();
1344
1345                for (; curIt != endIt; ++curIt)
1346                {
1347                        if (*curIt == ref)
1348                                return;
1349                }
1350
1351                missingMenuReferences[menuName].push_back(ref);
1352        }
1353}
1354
1355string CARInside::TextFindFields(const string &inText, const string &fieldSeparator, int schemaInsideId, int rootLevel, bool findKeywords, const CRefItem *refItem)
1356{       
1357        CDocTextReferences textRefs(inText, fieldSeparator, schemaInsideId, rootLevel, findKeywords, refItem);
1358        return textRefs.TextFindFields();
1359}
1360
1361string CARInside::TextFindFields(Context &context, const std::string &inText, bool findKeywords, const CRefItem *refItem)
1362{
1363        return TextFindFields(inText, "$", context.getCurrentSchemaId(), context.getRootLevel(), findKeywords, refItem);
1364}
1365
1366string CARInside::XMLFindFields(string inText, int schemaInsideId, int rootLevel, const CRefItem *refItem)
1367{       
1368        try
1369        {
1370                if(inText.empty())
1371                        return "";
1372
1373                CARSchema schema(schemaInsideId);
1374                if (!schema.Exists())
1375                        return inText;
1376
1377                unsigned int fieldCount = schema.GetFields()->GetCount();
1378                for(unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
1379                {
1380                        CARField field(schemaInsideId, 0, fieldIndex);
1381
1382                        stringstream strmTmp;
1383                        strmTmp << "arFieldId=&quot;" << field.GetFieldId() << "&quot;";                       
1384
1385                        stringstream fieldLink;
1386                        fieldLink << "arFieldId=&quot;" << URLLink(field, rootLevel) << "&quot;";                                       
1387
1388                        unsigned int nLengthOrg = (unsigned int)inText.length();
1389
1390                        string fField = strmTmp.str();
1391                        inText = CUtil::StrReplace(fField, fieldLink.str(), inText);
1392
1393                        //if the string is longer because we have added a link (long string) we add a field reference
1394                        if(inText.length() > nLengthOrg) 
1395                        {
1396                                AddFieldReference(schema.GetInsideId(), field.GetInsideId(), *refItem);
1397                        }
1398                }
1399        }
1400        catch(exception& e)
1401        {
1402                cout << "EXCEPTION in XMLFindField: " << e.what() << endl;
1403        }
1404
1405        return inText;
1406}
1407
1408string CARInside::ServerObjectHistory(CARServerObject *obj, int rootLevel, bool noTableDescription)
1409{               
1410        stringstream strm;
1411        strm.str("");
1412
1413        try
1414        {
1415                stringstream historyLog;
1416                if(obj->GetChangeDiary() != NULL)
1417                {                               
1418                        ARDiaryList diaryList; ARZeroMemory(&diaryList);
1419                        ARStatusList status; ARZeroMemory(&status);
1420                        if(ARDecodeDiary(&this->arControl, const_cast<char*>(obj->GetChangeDiary()), &diaryList, &status)==AR_RETURN_OK)
1421                        {
1422                                if(diaryList.numItems > 0)
1423                                {
1424                                        for(unsigned int j=0; j<diaryList.numItems; j++)
1425                                        {
1426                                                historyLog << CUtil::DateTimeToHTMLString(diaryList.diaryList[j].timeVal) << " " << this->LinkToUser(diaryList.diaryList[j].user, rootLevel) << "<br/>" << endl;
1427                                                historyLog << diaryList.diaryList[j].value << "<br/><br/>" << endl;
1428                                        }
1429                                }
1430                                else
1431                                {
1432                                        historyLog << EmptyValue << endl;
1433                                }
1434                        }
1435                        FreeARDiaryList(&diaryList, false);
1436                        FreeARStatusList(&status, false);
1437                }
1438
1439                CTable tbl("history", "TblObjectHistory");
1440                tbl.AddColumn(20, "Description");
1441                tbl.AddColumn(80, "Value");
1442
1443                if (!noTableDescription)
1444                {
1445                        tbl.description = ImageTag(ImageTag::Document, rootLevel);
1446                        tbl.description+= "Change History";
1447                }
1448
1449                //Owner
1450                CTableRow tblRow("");
1451                tblRow.AddCellList(CTableCell("Owner"), CTableCell(this->LinkToUser(obj->GetOwner(), rootLevel)));
1452                tbl.AddRow(tblRow);
1453
1454                //Last changed         
1455                stringstream strmLastChanged;
1456                strmLastChanged.str("");
1457                strmLastChanged << CUtil::DateTimeToHTMLString(obj->GetTimestamp()) << " " << this->LinkToUser(obj->GetLastChanged(), rootLevel) << endl;
1458
1459                tblRow.AddCellList(CTableCell("Last changed"), CTableCell(strmLastChanged.str()));
1460                tbl.AddRow(tblRow);
1461
1462
1463                //History
1464                tblRow.AddCellList(CTableCell("History Log"), CTableCell(historyLog.str()));
1465                tbl.AddRow(tblRow);
1466
1467                //Helptext
1468                string tmpHelptext;
1469                if(obj->GetHelpText() != NULL)
1470                {
1471                        tmpHelptext = CUtil::StrReplace("\n", "<br/>", obj->GetHelpText());
1472                }
1473                else
1474                {
1475                  tmpHelptext = EmptyValue;
1476                }
1477
1478                tblRow.AddCellList(CTableCell("Helptext"), CTableCell(tmpHelptext));
1479                tbl.AddRow(tblRow);
1480
1481                strm << tbl;
1482        }
1483        catch(exception& e)
1484        {
1485                cout << "EXCEPTION writing server object history: " << e.what() << endl;
1486        }       
1487
1488        return strm.str();
1489}
1490
1491void CARInside::DoWork(int nMode)
1492{       
1493        // first step is to create directory structure
1494        Prepare();
1495
1496        // now extract resources (images, css, js and so on)
1497        ExtractResources();
1498
1499        // now load the object either from server or from file
1500        LoadServerObjects(nMode);
1501
1502        // now create navigation page based on supported server features
1503        { CNavigationPage navPage(appConfig); navPage.Write(); }
1504
1505        // build needed reference tables
1506        CScanMain::BuildReferences();
1507
1508        // write documentation
1509        Documentation();
1510}
1511
1512void CARInside::ParseVersionString(string version)
1513{
1514        char ver[40];
1515        int part = 0;
1516
1517        vMajor = 0;
1518        vMinor = 0;
1519        vRevision = 0;
1520
1521        unsigned int verPos=0;
1522        unsigned int verStart=0;
1523        for (; verPos < version.size(); ++verPos)
1524        {
1525                char c = version.at(verPos);
1526                if (c >= '0' && c <= '9' ) 
1527                {
1528                        ver[verPos] = c;
1529                        continue;
1530                }
1531                if (verPos > verStart)
1532                {
1533                        ver[verPos] = 0;
1534                        int num = atoi(&ver[verStart]);
1535                        switch (part)
1536                        {
1537                        case 0:
1538                                vMajor = num;
1539                                break;
1540                        case 1:
1541                                vMinor = num;
1542                                break;
1543                        case 2:
1544                                vRevision = num;
1545                                break;
1546                        }
1547                        ++part;
1548                        verStart = verPos + 1;
1549                }
1550                if (c != '.') break;
1551        }
1552        ver[verPos] = 0;
1553}
1554
1555void CARInside::ParseVersionString(int xmlVersion)
1556{
1557        if (xmlVersion <= arXmlVersion) return;
1558
1559        if (xmlVersion >= AR_XML_VERSION_750)
1560        {
1561                arServerVersion = "7.5.00";
1562                vMajor = 7; vMinor = 5; vRevision = 0;
1563        }
1564        else if (xmlVersion >= AR_XML_VERSION_710)
1565        {
1566                arServerVersion = "7.1.00";
1567                vMajor = 7; vMinor = 1; vRevision = 0;
1568        }
1569        else if (xmlVersion >= AR_XML_VERSION_700)
1570        {
1571                arServerVersion = "7.0.00";
1572                vMajor = 7; vMinor = 0; vRevision = 0;
1573        }
1574        else if (xmlVersion >= AR_XML_VERSION_600)
1575        {
1576                // 6.0 and 6.3 use the same export version number. To show keywords
1577                // and other things (in case of a 6.3 export file) correctly, the
1578                // version is set to 6.3
1579                arServerVersion = "6.03.00";
1580                vMajor = 6; vMinor = 3; vRevision = 0;
1581        }
1582        else if (xmlVersion >= AR_XML_VERSION_510)
1583        {
1584                arServerVersion = "5.1.00";
1585                vMajor = 5; vMinor = 1; vRevision = 0;
1586        }
1587        else if (xmlVersion >= AR_XML_VERSION_500)
1588        {
1589                arServerVersion = "5.0.00";
1590                vMajor = 5; vMinor = 0; vRevision = 0;
1591        }
1592        else if (xmlVersion >= AR_XML_VERSION_450)
1593        {
1594                arServerVersion = "4.5.00";
1595                vMajor = 4; vMinor = 5; vRevision = 0;
1596        }
1597}
1598
1599int CARInside::CompareServerVersion(int major, int minor, int revision)
1600{
1601        if (vMajor == major)
1602        {
1603                if (minor > -1)
1604                {
1605                        if (vMinor == minor)
1606                        {
1607                                if (revision > -1)
1608                                {
1609                                        if (vRevision == revision) return 0;
1610                                        if (vRevision < revision) return -1;
1611                                        if (vRevision > revision) return 1;
1612                                }
1613                                return 0;
1614                        }
1615                        if (vMinor < minor) return -1;
1616                        if (vMinor > minor) return 1;
1617                }
1618                return 0;
1619        }
1620        if (vMajor < major) return -1;
1621        /*if (vMajor > major)*/ return 1;
1622}
1623
1624#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
1625int CARInside::LoadImages()
1626{
1627        imageList.LoadFromServer();
1628        imageList.Sort();
1629        return imageList.GetCount();
1630}
1631
1632string CARInside::LinkToImage(unsigned int imageIndex, int rootLevel)
1633{
1634        CARImage image(imageIndex);
1635        if (image.Exists())
1636        {
1637                return URLLink(image, rootLevel);
1638        }
1639        return EmptyValue;
1640}
1641
1642string CARInside::LinkToImage(const string &imageName, int rootLevel)
1643{
1644        int imageIndex = imageList.FindImage(imageName.c_str());
1645        if (imageIndex < 0)
1646        {
1647                stringstream strm;
1648                ObjNotFound notFound(strm);
1649                notFound << imageName;
1650                notFound.End();
1651                return strm.str();
1652        }
1653        else
1654        {
1655                return LinkToImage(imageIndex, rootLevel);
1656        }
1657}
1658#endif // AR_CURRENT_API_VERSION >= AR_API_VERSION_750
1659
1660bool CARInside::WriteHTAccess()
1661{
1662        stringstream strm;
1663        strm << this->appConfig.targetFolder << "/" << ".htaccess";
1664
1665        if (FileExists(strm.str()))
1666                return true;            // if file is already there, it should be configured correctly
1667
1668        try
1669        {
1670                string fileName = strm.str();
1671                LOG << "Save file '" << fileName;
1672
1673                ofstream fout(fileName.c_str(), ios::out);
1674                fout << "RemoveType .gz" << endl << "AddEncoding gzip .gz";
1675                fout.close();
1676        }
1677        catch (exception &e)
1678        {
1679                stringstream erStrm;
1680                erStrm << "Error saving file '" << strm.str() << "' to disk. Error: " << e.what();
1681                throw(AppException(erStrm.str(), "undefined", "FileIo"));
1682        }
1683        return true;
1684}
1685
1686void CARInside::SetupOverlaySupport()
1687{
1688#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
1689        if (CompareServerVersion(7,6,4) >= 0 && appConfig.bOverlaySupport)
1690        {
1691                ARStatusList status; ARZeroMemory(&status);
1692                ARValueStruct value;
1693                value.dataType = AR_DATA_TYPE_CHAR;
1694                value.u.charVal = (char*)AR_OVERLAY_CLIENT_MODE_FULL;
1695                if (ARSetSessionConfiguration(&arControl, AR_SESS_CONTROL_PROP_API_OVERLAYGROUP, &value, &status) != AR_RETURN_OK)
1696                        cerr << "SetSessionConfiguration failed: " << BuildMessageAndFreeStatus(status);
1697        }
1698#endif
1699}
1700
1701void CARInside::ExtractResources()
1702{
1703        try
1704        {
1705                ResourceFileLocatorAndExtractor resExtractor("arires.tgz");
1706                resExtractor.ExtractTo(appConfig.targetFolder);
1707        }
1708        catch (std::exception &ex)
1709        {
1710                cerr << "Error while extracting resources: " << ex.what() << endl;
1711        }
1712}
Note: See TracBrowser for help on using the repository browser.