source: branches/work_304/ARInside.cpp @ 405

Revision 405, 69.9 KB checked in by jls17, 6 years ago (diff)
  • changed some of the still existent calls to CARInside::GetSchemaInsideId? and replaced them by lookups via CARSchema
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/DocCustomWorkflow.h"
46
47#include "output/Table.h"
48#include "output/WebUtil.h"
49#include "output/NavigationPage.h"
50
51#include "output/IFileStructure.h"
52#include "output/FileNaming.h"
53
54#include "scan/ScanMain.h"
55
56#include "util/ResourceFileLocatorAndExtractor.h"
57
58/////////
59// the following file is generated via a pre-build step using "svnrev_template.h" as template.
60// The $WCREV$ keyword of the template is replaced with the revision number.
61#include "svnrev.h"
62
63/////////
64// version information block
65#define VERSION "3.0.4"
66#if defined(_DEBUG)
67#define VERSION_STR VERSION "." SVN_REV_STR " Debug"
68#elif defined(_ARINSIDE_BETA)
69#define VERSION_STR VERSION "." SVN_REV_STR " Beta"
70#else
71#define VERSION_STR VERSION "." SVN_REV_STR
72#endif
73const string AppVersion = VERSION_STR;
74/////////
75
76
77using namespace OUTPUT;
78
79// some kind of singleton pattern to keep compatibility
80CARInside* CARInside::pInsideInstance = NULL;
81
82CARInside::CARInside(AppConfig &appConfig)
83{
84        this->appConfig = appConfig;
85        this->globalFieldList.clear();
86        this->overlayMode = 1; // TODO: this is the default value for ars764. check for later versions
87
88        this->nDurationLoad = 0;
89        this->nDurationDocumentation = 0;
90
91        this->vMajor = 0;
92        this->vMinor = 0;
93        this->vRevision = 0;
94        this->arXmlVersion = 0;
95
96        if (appConfig.oldNaming)
97                SetFileNamingStrategy(new FileNaming::DefaultFileNamingStrategy());
98        else
99                SetFileNamingStrategy(new FileNaming::ObjectNameFileNamingStrategy());
100
101        if (CARInside::pInsideInstance == NULL) 
102                CARInside::pInsideInstance = this;
103
104        ARZeroMemory(&emptyPropList); // init struct; see lists/ARListHelpers.h
105}
106
107CARInside::~CARInside(void)
108{
109        DestroyFileNamingStrategy();
110}
111
112int CARInside::Init(string user, string pw, string server, int port, int rpc)
113{
114        cout << endl << "Connecting to server " << server << "..." << endl;
115
116        ARStatusList status;
117
118        ARZeroMemory(&arControl);
119        ARZeroMemory(&status);
120
121        if(this->appConfig.bUseUtf8)
122                strcpy(arControl.localeInfo.charSet, "UTF-8");
123
124        strncpy(arControl.user, user.c_str(), AR_MAX_NAME_SIZE);
125        arControl.user[AR_MAX_NAME_SIZE]='\0';
126        strncpy(arControl.password, pw.c_str(), AR_MAX_PASSWORD_SIZE);
127        arControl.password[AR_MAX_PASSWORD_SIZE]='\0';
128        strncpy(arControl.server, server.c_str(), AR_MAX_SERVER_SIZE);
129        arControl.server[AR_MAX_SERVER_SIZE]='\0';
130
131        int nResult = ARInitialization(&this->arControl,&status);
132        if (nResult != AR_RETURN_OK)
133        {
134                cout << "Initilization of ARAPI returned: " << nResult << " (" << CAREnum::ActiveLinkMessageType(nResult) << ")" << endl;
135                cout << BuildMessageAndFreeStatus(status);
136                return nResult;
137        }
138
139        if(server == "" && nResult == AR_RETURN_OK) // Filemode
140        {
141                return AR_RETURN_OK;
142        }
143
144        if ( nResult == AR_RETURN_OK)
145        {
146                if(port>0)
147                {
148                        nResult = ARSetServerPort(&this->arControl, this->arControl.server, port, rpc, &status);
149                        if (nResult != AR_RETURN_OK)
150                        {
151                                throw(AppException(BuildMessageAndFreeStatus(status), "undefined", "ARSystem"));
152                        }
153                }
154
155                if(this->appConfig.apiTimeout > 120) // at least 120 seconds api timeout
156                {
157                        ARValueStruct val; 
158                        for (unsigned int valId = AR_SESS_TIMEOUT_NORMAL; valId <= AR_SESS_TIMEOUT_XLONG; ++valId)
159                        {
160                                ARZeroMemory(&val);
161                                nResult = ARGetSessionConfiguration(&this->arControl, valId, &val, &status);
162
163                                // validate result
164                                if (nResult != AR_RETURN_OK) continue;  // ok, if this fails, dont bother .. next one
165                                if (val.dataType != AR_DATA_TYPE_INTEGER) continue;
166                                if (val.u.intVal > this->appConfig.apiTimeout) continue;
167
168                                // setup value
169                                val.dataType = AR_DATA_TYPE_INTEGER;
170                                val.u.intVal = this->appConfig.apiTimeout;
171
172                                // now configure session
173                                nResult = ARSetSessionConfiguration(&this->arControl, valId, &val, &status);
174                                if (nResult != AR_RETURN_OK)
175                                {
176                                        cout << "Setting session timeout failed: " << BuildMessageAndFreeStatus(status);
177                                }
178                        }
179                }
180
181                if(nResult == AR_RETURN_OK)
182                {
183                        ARBoolean isAdmin, isSubadmin, hasCustomize;
184                        nResult = ARVerifyUser(&this->arControl, &isAdmin, &isSubadmin, &hasCustomize, &status);
185                       
186                        if (nResult != AR_RETURN_OK)
187                        {
188                                throw(AppException(BuildMessageAndFreeStatus(status), "undefined", "ARSystem"));
189                        }
190                        FreeARStatusList(&status, false);
191
192                        serverInfoList.LoadAndGetValue(AR_SERVER_INFO_HOSTNAME, StoreTo(this->srvHostName));
193                        serverInfoList.LoadAndGetValue(AR_SERVER_INFO_FULL_HOSTNAME, StoreTo(this->srvFullHostName));
194                        serverInfoList.LoadAndGetValue(AR_SERVER_INFO_VERSION, StoreTo(this->arServerVersion));
195
196                        ParseVersionString(this->arServerVersion);
197
198#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
199                        if (CompareServerVersion(7,6,4) >= 0)
200                                serverInfoList.LoadAndGetValue(AR_SERVER_INFO_OVERLAY_MODE, StoreTo(this->overlayMode));
201#endif
202                        cout << "User '" << this->arControl.user <<"' connected to server " << srvFullHostName << endl;
203
204                        blackList.LoadFromServer(appConfig.blackList);
205                }
206        }
207
208        FreeARStatusList(&status, false);
209        return nResult;
210}
211
212int CARInside::Terminate(void)
213{
214        ARStatusList status;
215        ARZeroMemory(&status);
216
217        ARTermination(&this->arControl, &status);
218       
219        FreeARStatusList(&status, false);
220        return 0;
221}
222
223bool CARInside::FileExists(string fName)
224{
225        bool result = FileSystemUtil::FileExistsAndReadable(fName);
226        if (result)
227                cout << fName << " exists" << endl;
228        return result;
229}
230
231
232void CARInside::Prepare(void)
233{       
234        CDocMain *docMain = new CDocMain();
235
236        if( docMain->Index() == 1)
237        {
238                InitFileNamingStrategy();
239                if (appConfig.bGZCompression)
240                        WriteHTAccess();
241        }
242
243        delete docMain;
244}
245
246bool CARInside::FieldreferenceExists(int schemaInsideId, int fieldInsideId, const CRefItem &refItem)
247{
248        CARField fld(schemaInsideId, fieldInsideId);
249        if (!fld.Exists()) return false;
250
251        return fld.ReferenceExists(refItem);
252}
253
254void CARInside::LoadServerObjects(int nMode)
255{
256        CAppTimer mTimer;
257        mTimer.StartTimer();
258
259        if(nMode==1)
260        {
261                this->LoadFromFile();
262        }
263        else
264        {
265                this->LoadFromServer();
266        }
267        mTimer.EndTimer();
268        this->nDurationLoad = mTimer.GetDuration();
269}
270
271void CARInside::LoadFromFile(void)
272{
273        try
274        {
275                cout << endl << "Loading objects from file '" << appConfig.objListXML << "'" << endl;
276
277                ARStatusList status;
278                ARZeroMemory(&status);
279
280                ARXMLInputDoc xmlInputDoc;
281                xmlInputDoc.docType = AR_XML_DOC_FILE_NAME;
282                xmlInputDoc.u.fileName = (char*)appConfig.objListXML.c_str();
283
284                ARXMLParsedStream parsedStream;
285                ARStructItemList parsedObjects;
286                unsigned int xmlDocVersion = 0;
287
288                if(ARParseXMLDocument(&this->arControl, 
289                        &xmlInputDoc,
290                        NULL,
291                        &parsedStream,
292                        &parsedObjects,
293                        NULL,
294                        &status) == AR_RETURN_OK)
295                {                       
296                        cout << parsedObjects.numItems << " items loaded." << endl;
297
298                        unsigned int schemaCount = 0;
299                        unsigned int imagesCount = 0;
300                        unsigned int activelinkCount = 0;
301                        unsigned int filterCount = 0;
302                        unsigned int escalationCount = 0;
303                        unsigned int containerCount = 0;
304                        unsigned int menuCount = 0;
305
306                        for (unsigned int i=0; i < parsedObjects.numItems; ++i)
307                        {
308                                switch (parsedObjects.structItemList[i].type)
309                                {
310                                case AR_STRUCT_ITEM_XML_SCHEMA:
311                                        ++schemaCount;
312                                        break;
313                                case AR_STRUCT_ITEM_XML_ACTIVE_LINK:
314                                        ++activelinkCount;
315                                        break;
316                                case AR_STRUCT_ITEM_XML_FILTER:
317                                        ++filterCount;
318                                        break;
319                                case AR_STRUCT_ITEM_XML_ESCALATION:
320                                        ++escalationCount;
321                                        break;
322                                case AR_STRUCT_ITEM_XML_CONTAINER:
323                                        ++containerCount;
324                                        break;
325                                case AR_STRUCT_ITEM_XML_CHAR_MENU:
326                                        ++menuCount;
327                                        break;
328#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
329                                case AR_STRUCT_ITEM_XML_IMAGE:
330                                        ++imagesCount; 
331                                        break;
332#endif
333                                }
334                        }
335
336                        if (schemaCount > 0) schemaList.Reserve(schemaCount);
337                        if (activelinkCount > 0) alList.Reserve(activelinkCount);
338                        if (filterCount > 0) filterList.Reserve(filterCount);
339                        if (escalationCount > 0) escalationList.Reserve(escalationCount);
340                        if (containerCount > 0) containerList.Reserve(containerCount);
341                        if (menuCount > 0) menuList.Reserve(menuCount);
342#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
343                        if (imagesCount > 0) imageList.Reserve(imagesCount);
344#endif
345
346                        for(unsigned int i=0; i< parsedObjects.numItems; i++)
347                        {
348                                switch(parsedObjects.structItemList[i].type)
349                                {                                               
350                                case AR_STRUCT_ITEM_XML_FILTER:
351                                        {
352                                                LOG << "Loading Filter: " << parsedObjects.structItemList[i].name; 
353
354                                                int objInsideId = filterList.AddFilterFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
355
356                                                if (objInsideId > -1)
357                                                {
358                                                        ParseVersionString(xmlDocVersion);
359                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
360                                                }
361                                        }
362                                        break;
363                                case AR_STRUCT_ITEM_XML_SCHEMA:
364                                        {
365                                                LOG << "Loading Form: " << parsedObjects.structItemList[i].name;
366
367                                                int objInsideId = schemaList.AddSchemaFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
368
369                                                if (objInsideId > -1)
370                                                {
371                                                        ParseVersionString(xmlDocVersion);
372                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
373                                                }
374                                        }
375                                        break;                                 
376                                case AR_STRUCT_ITEM_XML_ACTIVE_LINK:
377                                        {
378                                                LOG << "Loading ActiveLink: " << parsedObjects.structItemList[i].name; 
379
380                                                int objInsideId = alList.AddActiveLinkFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
381
382                                                if (objInsideId > -1)
383                                                {
384                                                        ParseVersionString(xmlDocVersion);
385                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
386                                                }
387                                        }
388                                        break;
389                                case AR_STRUCT_ITEM_XML_CHAR_MENU:
390                                        {
391                                                LOG << "Loading CharMenu: " << parsedObjects.structItemList[i].name; 
392
393                                                int objInsideId = menuList.AddMenuFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
394
395                                                if (objInsideId > -1)
396                                                {
397                                                        ParseVersionString(xmlDocVersion);
398                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
399                                                }
400                                        }
401                                        break;
402                                case AR_STRUCT_ITEM_XML_ESCALATION:
403                                        {
404                                                LOG << "Loading Escalation: " << parsedObjects.structItemList[i].name; 
405
406                                                int objInsideId = escalationList.AddEscalationFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
407
408                                                if (objInsideId > -1)
409                                                {
410                                                        ParseVersionString(xmlDocVersion);
411                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
412                                                }
413                                        }
414                                        break;
415                                case AR_STRUCT_ITEM_XML_CONTAINER:
416                                        {
417                                                LOG << "Loading Container: " << parsedObjects.structItemList[i].name; 
418
419                                                int objInsideId = containerList.AddContainerFromXML(parsedStream, parsedObjects.structItemList[i].name, &xmlDocVersion);
420
421                                                if (objInsideId > -1)
422                                                {
423                                                        ParseVersionString(xmlDocVersion);
424                                                        LOG << " (InsideID: " << objInsideId << ") [OK]" << endl;
425                                                }
426                                        }
427                                        break;
428#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
429                                case AR_STRUCT_ITEM_XML_IMAGE:
430                                        {
431                                                LOG << "Loading Image: " << parsedObjects.structItemList[i].name;
432                                               
433                                                int imageInsideId = imageList.AddImageFromXML(parsedStream, parsedObjects.structItemList[i].name);
434                                               
435                                                // dont know why bmc has decided to remove the arDocVersion parameter from the
436                                                // ARGetImageFromXML api call. Now in case the xml-file contains only images we
437                                                // dont have a version at all. So we set it to version 7.5 by default. if other
438                                                // objects are present they will overwrite this version if it is a 7.5+ version.
439                                                ParseVersionString(AR_XML_VERSION_750);
440
441                                                if (imageInsideId > -1)
442                                                {
443                                                        LOG << " (InsideID: " << imageInsideId << ") [OK]" << endl;
444                                                }
445                                        }
446                                        break;
447#endif
448#if _DEBUG
449                                default:
450                                        cout << "Unused object type: [" << parsedObjects.structItemList[i].type << "] " << parsedObjects.structItemList[i].name << endl;
451                                        break;
452#endif
453                                }       
454                        }               
455                       
456                        schemaList.Sort();
457                        alList.Sort();
458                        filterList.Sort();
459                        escalationList.Sort();
460                        containerList.Sort();
461                        menuList.Sort();
462#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
463                        imageList.Sort();
464#endif
465                }
466                else
467                {
468                        cout << "An error occured parsing the xml document '" << appConfig.objListXML << "'" << endl;
469                        cout << BuildMessageAndFreeStatus(status);
470                }
471                if (!arServerVersion.empty())
472                        cout << "server version: " << arServerVersion << endl;
473
474                FreeARXMLParsedStream(&parsedStream, false);
475                FreeARStatusList(&status, false);
476        } 
477        catch (...)
478        { 
479                cerr << "EXCEPTION loading server objects from xml file." << endl; 
480        }
481}
482
483void CARInside::LoadFromServer(void)
484{
485        cout << endl << "Loading objects from server '" << appConfig.serverName << "'" << endl;
486        cout << "server version: " << arServerVersion << endl;
487
488        if (appConfig.slowObjectLoading)
489        {
490                cout << "NOTE: Fast object loading disabled!" << endl;
491        }
492
493        //LoadServerInfoList   
494        if(appConfig.bLoadServerInfoList)
495        {
496                cout << "Start loading Server Information:" << endl;
497                serverInfoList.Load();
498                cout << serverInfoList.GetCount() << " server settings loaded" << endl;
499        }
500        else
501                cout << endl << "Loading Server Informations [SKIPPED]" << endl;
502
503        SetupOverlaySupport();
504
505        //LoadUserList
506        if(appConfig.bLoadUserList)
507        {
508                cout << endl << "Start loading Users:" << endl;         
509                userList.LoadFromServer();
510                cout << userList.GetCount() << " Users loaded" << endl;
511        }
512        else
513                cout << endl << "Loading Users [SKIPPED]" << endl;
514
515
516        //LoadGroupList
517        if(appConfig.bLoadGroupList)
518        {
519                cout << endl << "Start loading Groups:" << endl;               
520                groupList.LoadFromServer();
521                cout << groupList.GetCount() << " Groups loaded" << endl;
522        }
523        else
524                cout << endl << "Loading Groups [SKIPPED]" << endl;
525
526        //LoadRoleList
527        if(appConfig.bLoadRoleList)
528        {
529                cout << endl << "Start loading Roles:" << endl;         
530                roleList.LoadFromServer();
531                cout << (unsigned int)roleList.GetCount() << " Roles loaded" << endl;
532        }
533        else
534                cout << endl << "Loading Roles [SKIPPED]" << endl;
535
536        //ActiveLinks           
537        cout << endl << "Start loading Active Links:" << endl;
538        int nResult = LoadActiveLinks();
539        cout << nResult << " Active Links loaded" << endl;
540
541
542        //Filters       
543        cout << endl << "Start loading Filters:" << endl;
544        nResult = LoadFilters();
545        cout << nResult << " Filters loaded" << endl;
546
547        //Container     
548        cout << endl << "Start loading Containers:" << endl;
549        nResult = LoadContainer();
550        cout << nResult << " Containers loaded" << endl;
551
552        //Escalations   
553        cout << endl << "Start loading Escalations:" << endl;
554        nResult = LoadEscalations();
555        cout << nResult << " Escalations loaded" << endl;
556
557        //CharMenus     
558        cout << endl << "Start loading Menus:" << endl;
559        nResult = LoadCharMenus();
560        cout << nResult << " Menus loaded" << endl;
561
562        //Images
563#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
564        if (CompareServerVersion(7,5) >= 0)
565        {
566                cout << endl << "Start loading Images:" << endl;
567                nResult = LoadImages();
568                cout << nResult << " Images loaded" << endl;
569        }
570#endif
571
572        //Load schemas
573        int insideId = 0;
574        cout << endl << "Start loading Forms:" << endl;
575
576        nResult = LoadForms();
577        cout << nResult << " Forms loaded" << endl << endl;
578
579        // TODO: if we want to keep the old output, we need to iterate the forms and count all types
580        ////Regular forms
581        //nResult = LoadForms(AR_LIST_SCHEMA_REGULAR, insideId);
582        //cout << nResult << " Regular Forms loaded" << endl;
583
584        ////Dialogs
585        //nResult = LoadForms(AR_LIST_SCHEMA_DIALOG, insideId);
586        //cout << nResult << " Dialog Forms loaded" << endl;
587
588        ////Join
589        //nResult = LoadForms(AR_LIST_SCHEMA_JOIN, insideId);
590        //cout << nResult << " Join Forms loaded" << endl;
591
592        ////Vendor
593        //nResult = LoadForms(AR_LIST_SCHEMA_VENDOR, insideId);
594        //cout << nResult << " Vendor Forms loaded" << endl;
595
596        ////View
597        //nResult = LoadForms(AR_LIST_SCHEMA_VIEW, insideId);
598        //cout << nResult << " View Forms loaded" << endl << endl;
599}
600
601int CARInside::LoadForms()
602{
603        try
604        {
605                schemaList.LoadFromServer();
606                schemaList.Sort();
607        }
608        catch(exception& e)
609        {
610                cout << "EXCEPTION loading Forms: " << e.what() << endl;
611        }
612
613        return schemaList.GetCount();
614}
615
616int CARInside::LoadContainer(void)
617{
618        try
619        {
620                containerList.LoadFromServer();
621                containerList.Sort();           
622        }
623        catch(exception& e)
624        {
625                cout << "EXCEPTION loading Container: " << e.what() << endl;
626        }
627
628        return containerList.GetCount();
629}
630
631int CARInside::LoadCharMenus(void)
632{
633        try
634        {
635                menuList.LoadFromServer();
636                menuList.Sort();
637        }
638        catch(exception& e)
639        {
640                cout << "EXCEPTION loading Menus: " << e.what() << endl;
641        }
642
643        return menuList.GetCount();
644}
645
646int CARInside::LoadEscalations(void)
647{
648        try
649        {
650                escalationList.LoadFromServer();
651                escalationList.Sort();
652        }
653        catch(exception& e)
654        {
655                cout << "EXCEPTION loading Escalations: " << e.what() << endl;
656        }
657
658        return escalationList.GetCount();
659}
660
661int CARInside::LoadFilters(void)
662{
663        try
664        {
665                filterList.LoadFromServer();
666                filterList.Sort();
667        }
668        catch(exception& e)
669        {
670                cout << "EXCEPTION loading Filters: " << e.what() << endl;
671        }
672
673        return filterList.GetCount();
674}
675
676int CARInside::LoadActiveLinks(void)
677{
678        try
679        {
680                alList.LoadFromServer();
681                alList.Sort();
682        }
683        catch(exception& e)
684        {
685                cout << "EXCEPTION loading ActiveLinks: " << e.what() << endl;
686        }
687        return alList.GetCount();
688}
689
690void CARInside::Documentation(void)
691{       
692        CAppTimer mTimer;
693        mTimer.StartTimer();
694
695        string strValue = objectNameFirstCharLetters; // "abcdefghijklmnopqrstuvwxyz0123456789#";
696        CDocMain *docMain = new CDocMain();
697
698        //Server information
699        docMain->ServerInfoList();
700
701        // container object count per first char
702        vector<int> algObjCount; algObjCount.resize(38);
703        vector<int> appObjCount; appObjCount.resize(38);
704        vector<int> pklObjCount; pklObjCount.resize(38);
705        vector<int> ftgObjCount; ftgObjCount.resize(38);
706        vector<int> wbsObjCount; wbsObjCount.resize(38);
707
708        CDocSummaryInfo indexSummary(*this, "");        // this is the object for the summary start page (it's written at the end of this function)
709
710        //ContainerList
711        indexSummary.alguideCount = docMain->ContainerList(ARCON_GUIDE, "ContainerList (ActiveLinkGuide)", "*", algObjCount);
712        indexSummary.applicationCount = docMain->ContainerList(ARCON_APP, "ContainerList (Application)", "*", appObjCount);
713        indexSummary.packlistCount = docMain->ContainerList(ARCON_PACK, "ContainerList (PackingList)", "*", pklObjCount);
714        indexSummary.fltguideCount = docMain->ContainerList(ARCON_FILTER_GUIDE, "ContainerList (FilterGuide)", "*", ftgObjCount);
715        indexSummary.webserviceCount = docMain->ContainerList(ARCON_WEBSERVICE, "ContainerList (Webservice)", "*", wbsObjCount);
716        for (unsigned int i = 0; i < strValue.size(); ++i)
717        {               
718                docMain->ContainerList(ARCON_GUIDE, "GuideList", std::string(1, strValue.at(i)), algObjCount);
719                docMain->ContainerList(ARCON_APP, "ApplicationList", std::string(1, strValue.at(i)), appObjCount);
720                docMain->ContainerList(ARCON_PACK, "PackinglistList", std::string(1, strValue.at(i)), pklObjCount);
721                docMain->ContainerList(ARCON_FILTER_GUIDE, "FilterGuideList", std::string(1, strValue.at(i)), ftgObjCount);
722                docMain->ContainerList(ARCON_WEBSERVICE, "WebserviceList", std::string(1, strValue.at(i)), wbsObjCount);
723        }
724
725        //Application Details
726        int nTmpCnt = 1;
727
728        //Create documentation here to fill objects applicationName reference information       
729        cout << "Starting Container Documentation" << endl;
730
731        unsigned int cntCount = this->containerList.GetCount();
732        for ( unsigned int cntIndex = 0; cntIndex < cntCount; ++cntIndex )
733        {
734                CARContainer cont(cntIndex);
735
736                switch(cont.GetType())
737                {
738                case ARCON_APP:
739                        {
740                                LOG << "Application [" << (cntIndex + 1) << "-" << cntCount << "] '" << cont.GetName() << "': ";
741                                CDocApplicationDetails appDetails(cont);
742                                appDetails.Documentation();
743                        }
744                        break;
745                default:
746                        {
747                                // TODO: is this output really correct? All other container types are documented and LOGged within the next loop!
748                                LOG << "Container [" << (cntIndex + 1) << "-" << cntCount << "] '" << cont.GetName() << "' [OK]" << endl;
749                        }
750                        break;
751                }
752
753                nTmpCnt++;
754        }
755
756        unsigned int tmpCount = this->containerList.GetCount();
757        for ( unsigned int cntIndex = 0; cntIndex < tmpCount; ++cntIndex )
758        {
759                CARContainer cont(cntIndex);
760                switch(cont.GetType())
761                {
762                case ARCON_WEBSERVICE:
763                        {
764                                LOG << "Webservice [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
765                                CDocWebserviceDetails wsDetails(cont);
766                                wsDetails.Documentation();
767                        }
768                        break;
769                case ARCON_GUIDE:
770                        {
771                                LOG << "ActiveLinkGuide [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
772                                CDocAlGuideDetails guideDetails(cont);
773                                guideDetails.Documentation();
774                        }
775                        break;
776                case ARCON_FILTER_GUIDE:
777                        {
778                                LOG << "FilterGuide [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
779                                CDocFilterGuideDetails fltGuideDetails(cont);
780                                fltGuideDetails.Documentation();
781                        }
782                        break;
783                case ARCON_PACK:
784                        {
785                                LOG << "PackingList [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "': ";
786                                CDocPacklistDetails packDetails(cont);
787                                packDetails.Documentation();
788                        }
789                        break;
790                case ARCON_APP:
791                        {
792                                LOG << "Application [" << (cntIndex + 1) << "-" << tmpCount << "] '" << cont.GetName() << "' [OK]" << endl;
793                        }
794                        break;
795                }
796
797                nTmpCnt++;
798        }
799
800        // active link object count per first char
801        vector<int> alObjCount; alObjCount.resize(38);
802
803        //ActiveLink List
804        indexSummary.activelinkCount = docMain->ActiveLinkList("*", alObjCount);
805        for (unsigned int i = 0; i < strValue.size(); ++i)
806        {               
807                docMain->ActiveLinkList(std::string(1, strValue.at(i)), alObjCount);
808        }       
809
810        docMain->ActiveLinkActionList();
811
812        //ActiveLink Details
813        tmpCount = alList.GetCount();
814        cout << "Starting ActiveLink Documentation" << endl;
815        for (unsigned int actlinkIndex = 0; actlinkIndex < tmpCount; ++actlinkIndex)
816        {       
817                LOG << "ActiveLink [" << actlinkIndex << "-" << nTmpCnt << "] '" << alList.ActiveLinkGetName(actlinkIndex) << "': ";
818                CDocAlDetails alDetails(actlinkIndex);
819                alDetails.Documentation();
820        }
821
822
823        // filter object count per first char
824        vector<int> fltObjCount; fltObjCount.resize(38);
825
826        //Filter List
827        indexSummary.filterCount = docMain->FilterList("*", fltObjCount);
828        for (unsigned int i = 0; i < strValue.size(); ++i)
829        {               
830                docMain->FilterList(std::string(1, strValue.at(i)), fltObjCount);
831        }       
832        docMain->FilterActionList();
833        docMain->FilterErrorHandlers();
834
835        //Filter Details
836        tmpCount = filterList.GetCount();
837        cout << "Starting Filter Documentation" << endl;
838        for (unsigned int filterIndex = 0; filterIndex < tmpCount; ++filterIndex)
839        {
840                LOG << "Filter [" << filterIndex << "-" << tmpCount << "] '" << filterList.FilterGetName(filterIndex) << "': ";
841                CDocFilterDetails filterDetails(filterIndex);
842                filterDetails.Documentation();
843        }
844
845
846        // escalation object count per first char
847        vector<int> escObjCount; escObjCount.resize(38);
848
849        //Escalation List
850        indexSummary.escalationCount = docMain->EscalationList("*", escObjCount);
851        for (unsigned int i = 0; i < strValue.size(); ++i)
852        {               
853                docMain->EscalationList(std::string(1, strValue.at(i)), escObjCount);
854        }
855        docMain->EscalationActionList();
856
857        //Escalation Details
858        tmpCount = escalationList.GetCount();
859        cout << "Starting Escalation Documentation" << endl;
860        for (unsigned int escalIndex = 0; escalIndex < tmpCount; ++escalIndex)
861        {
862                LOG << "Escalation [" << escalIndex << "-" << tmpCount << "] '" << escalationList.EscalationGetName(escalIndex) << "': ";
863                CDocEscalationDetails escalDetails(escalIndex);
864                escalDetails.Documentation();
865        }
866
867
868        // char menu object count per first char
869        vector<int> mnuObjCount; mnuObjCount.resize(38);
870
871        //CharMenus
872        indexSummary.menuCount = docMain->CharMenuList("*", mnuObjCount);
873        for (unsigned int i = 0; i < strValue.size(); ++i)
874        {               
875                docMain->CharMenuList(std::string(1, strValue.at(i)), mnuObjCount);
876        }       
877
878        // Char Menu Details
879        tmpCount = menuList.GetCount();
880        cout << "Starting Menu Documentation" << endl;
881        for (unsigned int menuIndex = 0; menuIndex < tmpCount; ++menuIndex)
882        {
883                LOG << "Menu [" << menuIndex << "-" << tmpCount << "] '" << menuList.MenuGetName(menuIndex) << "': ";
884                CDocCharMenuDetails menuDetails(menuIndex);
885                menuDetails.Documentation();
886        }
887
888        // schema types object first char count
889        vector<int> allObjCount; allObjCount.resize(38);
890
891        //Schema List
892        indexSummary.schemaCount = docMain->SchemaList(AR_SCHEMA_NONE,    CPageParams(PAGE_OVERVIEW, AR_STRUCT_ITEM_XML_SCHEMA)      , "Formlist (All)"    , "*", allObjCount);
893        docMain->SchemaList(AR_SCHEMA_REGULAR, CPageParams(PAGE_SCHEMA_REGULAR, AR_STRUCT_ITEM_XML_SCHEMA), "Formlist (Regular)", "*", allObjCount);
894        docMain->SchemaList(AR_SCHEMA_JOIN,    CPageParams(PAGE_SCHEMA_JOIN, AR_STRUCT_ITEM_XML_SCHEMA)   , "Formlist (Join)"   , "*", allObjCount);
895        docMain->SchemaList(AR_SCHEMA_VIEW,    CPageParams(PAGE_SCHEMA_VIEW, AR_STRUCT_ITEM_XML_SCHEMA)   , "Formlist (View)"   , "*", allObjCount);
896        docMain->SchemaList(AR_SCHEMA_DIALOG,  CPageParams(PAGE_SCHEMA_DIALOG, AR_STRUCT_ITEM_XML_SCHEMA) , "Formlist (Dialog)" , "*", allObjCount);
897        docMain->SchemaList(AR_SCHEMA_VENDOR,  CPageParams(PAGE_SCHEMA_VENDOR, AR_STRUCT_ITEM_XML_SCHEMA) , "Formlist (Vendor)" , "*", allObjCount);   
898        for (unsigned int i = 0; i < strValue.size(); ++i)
899        {               
900                docMain->SchemaList(AR_SCHEMA_NONE, CPageParams(strValue.at(i), AR_STRUCT_ITEM_XML_SCHEMA), "Formlist", std::string(1, strValue.at(i)), allObjCount);
901        }
902
903        //Schema and field Details
904        nTmpCnt=1;
905        unsigned int schemaCount = schemaList.GetCount();
906        cout << "Starting Schema Documentation" << endl;
907        for (unsigned int schemaIndex = 0; schemaIndex < schemaCount; ++schemaIndex)
908        {
909                int rootLevel = 2;
910                CARSchema schema(schemaIndex);
911
912                LOG << "Schema [" << (schemaIndex + 1) << "-" << schemaCount << "] '" << schema.GetName() << "': ";
913                CDocSchemaDetails *schemaDetails = new CDocSchemaDetails(schemaIndex, rootLevel);
914                schemaDetails->Documentation();
915                delete schemaDetails;
916
917
918                //VuiDetails
919                LOG << "VuiDetails Schema '" << schema.GetName() << "'" << endl;
920                unsigned int objCount = schema.GetVUIs()->GetCount();
921                for (unsigned int vuiIndex = 0; vuiIndex < objCount; ++vuiIndex)
922                {
923                        CARVui vui(schema.GetInsideId(), 0, vuiIndex);
924
925                        LOG << "SchemaView '" << vui.GetName() << "': ";
926                        CDocVuiDetails *vuiDetails = new CDocVuiDetails(schema.GetInsideId(), vui, rootLevel);
927                        vuiDetails->Documentation();
928                        delete vuiDetails;
929                }
930
931                //FieldDetails
932                LOG << "FieldDetails Schema '" << schema.GetName() << "'" << endl;             
933                objCount = schema.GetFields()->GetCount();
934                for (unsigned int fieldIndex = 0; fieldIndex < objCount; ++fieldIndex)
935                {       
936                        CARField field(schema.GetInsideId(), 0, fieldIndex);
937                        CDocFieldDetails *fieldDetails = new CDocFieldDetails(schema.GetInsideId(), field, rootLevel);
938                        fieldDetails->Documentation();
939                        delete fieldDetails;
940                }
941
942                nTmpCnt++;
943        }
944
945#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
946        // image object count per first char
947        vector<int> imgObjCount; imgObjCount.resize(38);
948
949        // Image
950        indexSummary.imageCount = docMain->ImageList("*", imgObjCount);
951        for (unsigned int i = 0; i < strValue.size(); ++i)
952        {               
953                docMain->ImageList(std::string(1, strValue.at(i)), imgObjCount);
954        }       
955
956        // Image Details
957        tmpCount = imageList.GetCount();
958        cout << "Starting Image Documentation" << endl;
959        for (unsigned int imgIndex = 0; imgIndex < tmpCount; ++imgIndex)
960        {
961                LOG << "Image [" << imgIndex << "-" << nTmpCnt << "] '" << imageList.ImageGetName(imgIndex) << "': ";
962
963                CDocImageDetails imgDetails(imgIndex);
964                imgDetails.Documentation();
965        }
966#endif
967
968        //GlobalFieldList
969        docMain->GlobalFieldList();     
970
971        //MessageList
972        docMain->MessageList(); 
973
974        //NotificationList
975        docMain->NotificationList();
976
977        //Analyzer
978        CDocAnalyzer *analyzer = new CDocAnalyzer();
979        analyzer->Documentation();
980        delete analyzer;
981
982        //Validation
983        CDocValidator *validator = new CDocValidator();
984        validator->Main();
985        delete validator;
986
987        {
988                CDocCustomWorkflow customWF;
989                customWF.Documentation();
990        }
991
992        // group count per first char
993        vector<int> grpObjCount; grpObjCount.resize(38);
994
995        //Group List
996        docMain->GroupList("*", grpObjCount);
997        for (unsigned int i = 0; i < strValue.size(); ++i)
998        {               
999                docMain->GroupList(std::string(1, strValue.at(i)), grpObjCount);
1000        }       
1001
1002
1003        //Group Details
1004        cout << "Starting Group Documentation" << endl;
1005
1006        tmpCount = groupList.GetCount();
1007        for (unsigned int groupIndex = 0; groupIndex < tmpCount; ++groupIndex)
1008        {
1009                CARGroup grp(groupIndex);
1010
1011                LOG << "Group [" << (groupIndex + 1) << "-" << tmpCount << "] '" << grp.GetName() << "': ";
1012                CDocGroupDetails grpDetails(grp);
1013                grpDetails.Documentation();
1014        }
1015
1016
1017        // role count per first char
1018        vector<int> roleObjCount; roleObjCount.resize(38);
1019
1020        //Role List
1021        docMain->RoleList("*", roleObjCount);
1022        for (unsigned int i = 0; i < strValue.size(); ++i)
1023        {               
1024                docMain->RoleList(std::string(1, strValue.at(i)), roleObjCount);
1025        }       
1026
1027        //Role Details
1028        cout << "Starting Role Documentation" << endl;
1029
1030        tmpCount = roleList.GetCount();
1031        for (unsigned int roleIndex = 0; roleIndex < tmpCount; ++roleIndex)
1032        {
1033                CARRole role(roleIndex);
1034
1035                LOG << "Role [" << (roleIndex + 1) << "-" << tmpCount << "] '" << role.GetName() << "': ";
1036                CDocRoleDetails roleDetails(role);
1037                roleDetails.Documentation();
1038        }
1039
1040
1041        // user count per first char
1042        vector<int> usrObjCount; usrObjCount.resize(38);
1043
1044        //Userlists
1045        docMain->UserList("*", usrObjCount);
1046        for (unsigned int i = 0; i < strValue.size(); ++i)
1047        {               
1048                docMain->UserList(std::string(1, strValue.at(i)), usrObjCount);
1049        }       
1050
1051        //User Details
1052        cout << "Starting User Documentation" << endl;
1053
1054        tmpCount = userList.GetCount();
1055        for (unsigned int userIndex = 0; userIndex < tmpCount; ++userIndex)
1056        {
1057                CARUser user(userIndex);
1058
1059                LOG << "User [" << (userIndex + 1) << "-" << tmpCount << "] '" << user.GetName() << "': ";
1060               
1061                CDocUserDetails userDetails(user);
1062                userDetails.Documentation();
1063        }
1064
1065        mTimer.EndTimer();
1066        this->nDurationDocumentation = mTimer.GetDuration();
1067
1068        indexSummary.Documentation();
1069
1070        delete docMain;
1071}
1072
1073string CARInside::GetFieldEnumValue(int schemaInsideId, int fieldInsideId, int enumPosition)
1074{
1075        CARField field(schemaInsideId, fieldInsideId);
1076        if (field.Exists())
1077        {
1078                if(field.GetDataType() == AR_DATA_TYPE_ENUM)
1079                {
1080                        const ARFieldLimitStruct& limits = field.GetLimits();
1081                        switch(limits.u.enumLimits.listStyle)
1082                        {
1083                        case AR_ENUM_STYLE_REGULAR:
1084                                if (static_cast<unsigned int>(enumPosition) < limits.u.enumLimits.u.regularList.numItems)
1085                                        return limits.u.enumLimits.u.regularList.nameList[enumPosition];
1086                                break;
1087                        case AR_ENUM_STYLE_CUSTOM:
1088                                for (unsigned int i=0; i < limits.u.enumLimits.u.customList.numItems; i++) { 
1089                                        if (limits.u.enumLimits.u.customList.enumItemList[i].itemNumber == enumPosition) 
1090                                                return limits.u.enumLimits.u.customList.enumItemList[i].itemName; 
1091                                } 
1092                                break;
1093                        case AR_ENUM_STYLE_QUERY:
1094                                return "QUERY";
1095                        }                                               
1096                }
1097        }
1098        return "";
1099}
1100
1101string CARInside::LinkToVui(const string& schemaName, int vuiInsideId, int fromRootLevel)
1102{
1103        CARSchema schema(schemaName);
1104        return LinkToVui(schema.GetInsideId(), vuiInsideId, fromRootLevel);
1105}
1106
1107string CARInside::LinkToVui(int schemaInsideId, int vuiInsideId, int fromRootLevel)
1108{
1109        CARVui vui(schemaInsideId, vuiInsideId);
1110        if (vui.Exists())
1111        {
1112                return vui.GetURL(fromRootLevel);
1113        }
1114        return "";
1115}
1116
1117string CARInside::LinkToField(const string& schemaName, int fieldInsideId, int fromRootLevel)
1118{       
1119        CARSchema schema(schemaName);
1120        return LinkToField(schema.GetInsideId(), fieldInsideId, fromRootLevel);
1121}
1122
1123string CARInside::LinkToField(int schemaInsideId, int fieldInsideId, const string& linkText, int fromRootLevel)
1124{       
1125        CARField field(schemaInsideId, fieldInsideId);
1126        if (field.Exists())
1127        {
1128                return field.GetURL(linkText, fromRootLevel);
1129        }
1130
1131        //Field has not been found
1132        stringstream tmp;
1133
1134        if(fieldInsideId > 0 && schemaInsideId > -1) //OpenWindow uses 0 what is no valid field
1135        {
1136                tmp << "<span class=\"fieldNotFound\">" << fieldInsideId << "</span>";
1137        }
1138        else
1139        {
1140                tmp << fieldInsideId;
1141        }
1142
1143        return tmp.str();
1144}
1145
1146string CARInside::LinkToField(int schemaInsideId, int fieldInsideId, int fromRootLevel)
1147{
1148        return LinkToField(schemaInsideId, fieldInsideId, "", fromRootLevel);
1149}
1150
1151// TODO: maybe change callers to LinkToField and remove this function completely
1152string CARInside::LinkToMenuField(int schemaInsideId, int fieldInsideId, int fromRootLevel)
1153{
1154        return LinkToField(schemaInsideId, fieldInsideId, fromRootLevel);
1155}
1156
1157string CARInside::LinkToSchemaTypeList(int schemaType, int rootLevel)
1158{
1159        unsigned int page = PAGE_OVERVIEW;
1160
1161        switch (schemaType)
1162        {
1163                case AR_SCHEMA_REGULAR: page = PAGE_SCHEMA_REGULAR; break;
1164                case AR_SCHEMA_JOIN: page = PAGE_SCHEMA_JOIN; break;
1165                case AR_SCHEMA_VIEW: page = PAGE_SCHEMA_VIEW; break;
1166                case AR_SCHEMA_DIALOG: page = PAGE_SCHEMA_DIALOG; break;
1167                case AR_SCHEMA_VENDOR: page = PAGE_SCHEMA_VENDOR; break;
1168        }
1169
1170        return CWebUtil::Link(CAREnum::SchemaType(schemaType), CPageParams(page), "", rootLevel);
1171}
1172
1173// TODO: add a function with parameter CARSchema instead of schemaInsideId to pass in the object directly
1174string CARInside::LinkToSchemaIndex(string indexName, int schemaInsideId, int fromRootLevel)
1175{
1176        CARSchema schema(schemaInsideId);
1177        CPageParams file(PAGE_SCHEMA_INDEXES, &schema);
1178        return CWebUtil::Link(indexName, file, "", fromRootLevel);
1179}
1180
1181string CARInside::LinkToSchema(int insideId, int fromRootLevel)
1182{
1183        CARSchema schema(insideId);
1184        if(schema.Exists())
1185        {
1186                return schema.GetURL(fromRootLevel);
1187        }
1188        return EmptyValue;
1189}
1190
1191string CARInside::LinkToSchema(const string& schemaName, int fromRootLevel)
1192{
1193        CARSchema schema(schemaName);
1194        if(schema.Exists())
1195        {
1196                return schema.GetURL(fromRootLevel);
1197        }
1198        return schemaName;
1199}
1200
1201int CARInside::SchemaGetInsideId(string searchObjName)
1202{
1203        CARSchema schema(searchObjName);
1204        if (schema.Exists())
1205        {
1206                return schema.GetInsideId();
1207        }
1208        return -1;
1209}
1210
1211string CARInside::LinkToUser(string loginName, int rootLevel)
1212{
1213        CARUser user(loginName);
1214
1215        if (user.Exists())
1216                return CWebUtil::Link(loginName, CPageParams(PAGE_DETAILS, &user), "", rootLevel);
1217
1218        return loginName;
1219}
1220
1221bool CARInside::ValidateGroup(const string& appRefName, int permissionId)
1222{
1223        if(permissionId >= 0)
1224        {
1225                return true;
1226        }
1227        else
1228        {
1229                CARRole role(permissionId, appRefName);
1230
1231                if (role.Exists())
1232                {
1233                        return true;
1234                }
1235        }
1236
1237        return false;
1238}
1239
1240string CARInside::LinkToGroup(const string& appRefName, int permissionId, int rootLevel)
1241{       
1242        if(permissionId >= 0)
1243        {
1244                CARGroup group(-1, permissionId);
1245                if (group.Exists())
1246                {
1247                        return CWebUtil::Link(group.GetName(), CPageParams(PAGE_DETAILS, &group), "group.gif", rootLevel);
1248                }               
1249        }
1250        else
1251        {
1252                if(!appRefName.empty())
1253                {
1254                        CARRole role(permissionId, appRefName);
1255
1256                        if(role.Exists())
1257                        {
1258                                return CWebUtil::Link(role.GetName(), CPageParams(PAGE_DETAILS, &role), "doc.gif", rootLevel);
1259                        }
1260                }
1261        }
1262
1263        stringstream strmTmp;
1264        strmTmp << permissionId;
1265        return strmTmp.str();
1266}
1267
1268string CARInside::LinkToAlRef(const CRefItem& refItem, int rootLevel)
1269{
1270        CARActiveLink al(refItem.GetObjectId());
1271        if (!al.Exists())
1272                return EmptyValue;
1273
1274        stringstream strmTmp;
1275        strmTmp << al.GetURL(rootLevel) << " (" << al.GetOrder() << ")";
1276        return strmTmp.str();
1277}
1278
1279string CARInside::LinkToAl(const string& alName, int fromRootLevel)
1280{
1281        CARActiveLink al(alName);
1282        if (!al.Exists())
1283                return alName;
1284
1285        return al.GetURL(fromRootLevel);
1286}
1287
1288string CARInside::LinkToAl(int alInsideId, int rootLevel)
1289{
1290        CARActiveLink al(alInsideId);
1291
1292        if (al.Exists())
1293                return al.GetURL(rootLevel);
1294
1295        return EmptyValue;
1296}
1297
1298string CARInside::LinkToFilterRef(int filterInsideId, int rootLevel)
1299{       
1300        CARFilter flt(filterInsideId);
1301        if (flt.Exists())
1302        {
1303                return LinkToFilterRef(&flt, rootLevel);
1304        }
1305        return EmptyValue;
1306}
1307
1308string CARInside::LinkToFilterRef(const CRefItem& refItem, int rootLevel)
1309{
1310        CARFilter flt(refItem.GetObjectId());
1311        if (flt.Exists())
1312        {
1313                return LinkToFilterRef(&flt, rootLevel);
1314        }
1315        return EmptyValue;
1316}
1317
1318string CARInside::LinkToFilterRef(CARFilter* filter, int rootLevel)
1319{
1320        stringstream strmTmp;
1321        strmTmp.str("");
1322
1323        if (filter != NULL)
1324                strmTmp << filter->GetURL(rootLevel) << " (" << filter->GetOrder() << ")";
1325
1326        return strmTmp.str();
1327}
1328
1329string CARInside::LinkToFilter(string filterName, int fromRootLevel)
1330{
1331        if (filterName.empty()) return filterName;
1332
1333        int fltInsideId = filterList.Find(filterName.c_str());
1334        if (fltInsideId > -1)
1335        {
1336                CARFilter flt(fltInsideId);
1337                return flt.GetURL(fromRootLevel);
1338        }
1339        return filterName;
1340}
1341
1342string CARInside::LinkToMenu(string menuName, int fromRootLevel)
1343{
1344        if (menuName.compare("$NULL$")==0)
1345        {
1346                return menuName;
1347        }
1348
1349        CARCharMenu menu(menuName);
1350        if (menu.Exists())
1351        {
1352                return menu.GetURL(fromRootLevel);
1353        }
1354
1355        //Menu has not been found
1356        //If the menu is missing, we just return the name of it. maybe link to the
1357        //"missing menus" page (must be implemented first) of CDocValidator later.
1358        return "<span class=\"fieldNotFound\">" + menuName + "</span>";
1359}
1360
1361string CARInside::LinkToMenu(const CRefItem& refItem, int rootLevel)
1362{
1363        CARCharMenu menu(refItem.GetObjectId());
1364        if (menu.Exists())
1365        {
1366                return menu.GetURL(rootLevel);
1367        }
1368
1369        return EmptyValue;
1370}
1371
1372string CARInside::LinkToEscalation(const string& escalationName, int fromRootLevel)
1373{
1374        CAREscalation escal(escalationName);
1375        if (escal.Exists())
1376        {
1377                return escal.GetURL(fromRootLevel);
1378        }
1379        return escalationName;
1380}
1381
1382string CARInside::LinkToEscalation(const CRefItem& refItem, int fromRootLevel)
1383{
1384        CAREscalation escal(refItem.GetObjectId());
1385        if (escal.Exists())
1386        {
1387                return escal.GetURL(fromRootLevel);
1388        }
1389        return EmptyValue;
1390}
1391
1392string CARInside::LinkToContainer(string containerName, int fromRootLevel)
1393{
1394        CARContainer cnt(containerName);
1395        if (cnt.Exists())
1396        {
1397                return cnt.GetURL(fromRootLevel);
1398        }
1399        return containerName;
1400}
1401
1402string CARInside::LinkToContainer(const CRefItem& refItem, int rootLevel)
1403{
1404        CARContainer cnt(refItem.GetObjectId());
1405        if (cnt.Exists())
1406        {
1407                return cnt.GetURL(rootLevel);
1408        }
1409        return EmptyValue;
1410}
1411
1412string CARInside::LinkToServerInfo(string srvName, int rootLevel)
1413{               
1414        string result;
1415
1416        if(strcmp(srvName.c_str(), "")==0)
1417        {
1418                return CWebUtil::Link(appConfig.serverName, CPageParams(PAGE_SERVER_INFO), "", rootLevel);
1419        }
1420        else if(strcmp(srvName.c_str(), AR_CURRENT_SERVER_TAG)==0 || strcmp(srvName.c_str(), AR_CURRENT_SCREEN_TAG)==0)
1421        {
1422                return CWebUtil::Link(appConfig.serverName, CPageParams(PAGE_SERVER_INFO), "", rootLevel);
1423        }
1424        else
1425        {
1426                return CWebUtil::Link(srvName, CPageParams(PAGE_SERVER_INFO), "", rootLevel);
1427        }
1428
1429
1430        return result;
1431}
1432
1433string CARInside::LinkToObjByRefItem(const CRefItem& refItem, int rootLevel)
1434{
1435        string result = EmptyValue;
1436
1437        switch(refItem.GetObjectType())
1438        {
1439        case AR_STRUCT_ITEM_XML_ACTIVE_LINK: 
1440                {
1441                        result = this->LinkToAlRef(refItem, rootLevel);
1442                }
1443                break;
1444        case AR_STRUCT_ITEM_XML_FILTER:
1445                {
1446                        result = this->LinkToFilterRef(refItem, rootLevel);
1447                }
1448                break;
1449        case AR_STRUCT_ITEM_XML_SCHEMA:
1450                {
1451                        result = this->LinkToSchema(refItem.GetObjectName(), rootLevel);
1452                }
1453                break;
1454        case AR_STRUCT_ITEM_XML_FIELD:
1455                {
1456                        result = this->LinkToField(refItem.GetObjectId(), refItem.GetSubObjectId(), rootLevel);
1457                }
1458                break;
1459        case AR_STRUCT_ITEM_XML_VUI:
1460                {
1461                        result = this->LinkToVui(refItem.GetObjectId(), refItem.GetSubObjectId(), rootLevel);
1462                }
1463                break;
1464        case AR_STRUCT_ITEM_XML_ESCALATION:
1465                {
1466                        result = this->LinkToEscalation(refItem, rootLevel);
1467                }
1468                break;
1469        case AR_STRUCT_ITEM_XML_CHAR_MENU:
1470                {
1471                        result = this->LinkToMenu(refItem, rootLevel);
1472                }
1473                break;         
1474        case AR_STRUCT_ITEM_XML_CONTAINER:
1475                {
1476                        result = this->LinkToContainer(refItem, rootLevel);
1477                }
1478                break;
1479//#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
1480//      case AR_STRUCT_ITEM_XML_IMAGE:
1481//              {
1482//                      result = this->LinkToImage(objName, rootLevel);
1483//              }
1484//              break;
1485//#endif
1486        }
1487
1488        return result;
1489}
1490
1491string CARInside::XmlObjEnabled(CARServerObject *obj)
1492{
1493        switch(obj->GetServerObjectTypeXML())
1494        {
1495        case AR_STRUCT_ITEM_XML_ACTIVE_LINK: 
1496                return CAREnum::ObjectEnable(static_cast<CARActiveLink*>(obj)->GetEnabled());
1497        case AR_STRUCT_ITEM_XML_FILTER:
1498                return CAREnum::ObjectEnable(static_cast<CARFilter*>(obj)->GetEnabled());
1499        case AR_STRUCT_ITEM_XML_ESCALATION:
1500                return CAREnum::ObjectEnable(static_cast<CAREscalation*>(obj)->GetEnabled());
1501        default:
1502                return "";
1503        }
1504}
1505
1506string CARInside::XmlObjEnabled(int arsStructItemType, string objName)
1507{
1508        switch(arsStructItemType)
1509        {
1510        case AR_STRUCT_ITEM_XML_ACTIVE_LINK: 
1511                {
1512                        CARActiveLink al(objName);
1513                        if (al.Exists())
1514                        {
1515                                return CAREnum::ObjectEnable(al.GetEnabled());
1516                        }
1517                }
1518                break;
1519        case AR_STRUCT_ITEM_XML_FILTER:
1520                {
1521                        int fltInsideId = filterList.Find(objName.c_str());
1522                        if (fltInsideId > -1)
1523                        {
1524                                return CAREnum::ObjectEnable(filterList.FilterGetEnabled(fltInsideId));
1525                        }
1526                }
1527                break;         
1528        case AR_STRUCT_ITEM_XML_ESCALATION:
1529                {
1530                        int escInsideId = escalationList.Find(objName.c_str());
1531                        if (escInsideId > -1)
1532                        {
1533                                return CAREnum::ObjectEnable(escalationList.EscalationGetEnabled(escInsideId));
1534                        }
1535                }
1536                break; 
1537        }
1538
1539        return "";
1540}
1541
1542void CARInside::AddFieldReference(int schemaId, int fieldId, const CRefItem& ref)
1543{
1544        if (ref.GetMessageId() == -1) return; // if no message id is specified, dont create a reference
1545
1546        CARHandle<> hObj(ref);
1547        if (appConfig.bOverlaySupport && hObj.Exists() && !IsVisibleObject(*hObj))
1548                return;
1549
1550        CARSchema schema(schemaId);
1551        CARField fld(schemaId, fieldId);
1552
1553        if (fld.Exists())
1554        {
1555                if (!fld.ReferenceExists(ref))
1556                        fld.AddReference(ref);
1557        }
1558        else if (schema.Exists())
1559        {
1560                schema.AddMissingFieldReference(fieldId, ref);
1561        }
1562        // TODO: create a list of missing schemas
1563        //else
1564        //{
1565        //      LOG << "Missing Schema!" << endl;
1566        //}
1567}
1568
1569void CARInside::AddMenuReference(const string& menuName, const CRefItem &ref)
1570{
1571        if (menuName == "$NULL$") return;
1572
1573        CARCharMenu menu(menuName);
1574
1575        if (menu.Exists())
1576        {
1577                // if the menu was found add the referece to it
1578                if (!menu.ReferenceExists(ref))
1579                        menu.AddReference(ref);
1580        }
1581        else
1582        {
1583                // if the menu is missing, add the name to the missing menus map and append the reference to it
1584                if (missingMenuReferences.find(menuName) != missingMenuReferences.end())
1585                {
1586                        missingMenuReferences.insert(pair<string, vector<CRefItem> >(menuName, vector<CRefItem>()));
1587                }
1588
1589                CARCharMenu::ReferenceList::iterator curIt = missingMenuReferences[menuName].begin();
1590                CARCharMenu::ReferenceList::iterator endIt = missingMenuReferences[menuName].end();
1591
1592                for (; curIt != endIt; ++curIt)
1593                {
1594                        if (*curIt == ref)
1595                                return;
1596                }
1597
1598                missingMenuReferences[menuName].push_back(ref);
1599        }
1600}
1601
1602string CARInside::TextFindFields(string inText, string fieldSeparator, int schemaInsideId, int rootLevel, bool findKeywords, const CRefItem *refItem)
1603{       
1604        try
1605        {
1606                if(inText.size() == 0)
1607                        return "";
1608
1609                CARSchema schema(schemaInsideId);
1610                if (!schema.Exists())
1611                        return inText;
1612
1613                string dummySeparator = "##"; //dummy placeholder to avoid infinite replacements
1614
1615                stringstream strmTmp;
1616
1617                string::size_type curPos = 0;
1618                string::size_type startPos = 0;
1619                string::size_type maxLen = inText.length();
1620                string::size_type fieldIdPos = 0;
1621
1622                char fieldId[20];
1623                char *enumId;    // points to the enum part of status history within fieldId later
1624                char *usrOrTime; // points to the "user or time" part of status history within fieldId later
1625
1626                while ((startPos = inText.find(fieldSeparator.at(0),curPos)) != std::string::npos)
1627                {
1628                        ++startPos;
1629                        strmTmp << inText.substr(curPos,startPos - curPos);
1630                        curPos = startPos;
1631
1632                        // reset
1633                        fieldIdPos = 0; 
1634                        fieldId[0] = 0;
1635                        enumId = NULL;
1636                        usrOrTime = NULL;
1637
1638                        for (curPos = startPos; curPos < maxLen; ++curPos)
1639                        {
1640                                char currChar = inText.at(curPos);
1641                                if (currChar == '-' && fieldIdPos != 0) 
1642                                        break; // - is only allowed at the beginning
1643                                if (currChar >= '0' && currChar <= '9' || currChar == '-' || currChar == '.')
1644                                {
1645                                        if (fieldIdPos + 1 == 20)
1646                                                break;  // max length .. that cant be a field
1647
1648                                        if (currChar != '.' && fieldIdPos > 1 && fieldId[fieldIdPos-1] == '.')
1649                                        {
1650                                                fieldId[fieldIdPos-1] = 0;
1651                                                if (enumId == NULL)
1652                                                        enumId = &fieldId[fieldIdPos];
1653                                                else if (usrOrTime == NULL)
1654                                                        usrOrTime = &fieldId[fieldIdPos];
1655                                                else
1656                                                        break; // uhh ohh
1657                                        }
1658                                        // copy it over
1659                                        fieldId[fieldIdPos++] = currChar;
1660                                        continue;
1661                                }
1662                                if (currChar == fieldSeparator.at(0))
1663                                {
1664                                        // end found
1665                                        fieldId[fieldIdPos] = 0;
1666
1667                                        if (fieldId[0] == 0)
1668                                                break;  // two $$ .. someone must be dreaming about more money
1669
1670                                        int iFieldId = atoi(fieldId);
1671                                        if (iFieldId > 0)
1672                                        {
1673                                                CARField field(schemaInsideId, iFieldId);
1674
1675                                                if (!field.Exists())
1676                                                        break;
1677
1678                                                // now link to the field
1679                                                strmTmp << field.GetURL(rootLevel);
1680                                                if (refItem != NULL)
1681                                                        AddFieldReference(schemaInsideId, iFieldId, *refItem);
1682
1683                                                // special handling for status history
1684                                                if (iFieldId == 15)
1685                                                {
1686                                                        if (enumId == NULL || usrOrTime == NULL) break;
1687
1688                                                        // resolve user or time attribute
1689                                                        int iUsrOrTime = atoi(usrOrTime);
1690                                                        const char* usrOrTimeStr = usrOrTime;
1691                                                        switch (iUsrOrTime)
1692                                                        {
1693                                                        case AR_STAT_HISTORY_USER:
1694                                                                usrOrTimeStr = "USER";
1695                                                                break;
1696                                                        case AR_STAT_HISTORY_TIME:
1697                                                                usrOrTimeStr = "TIME";
1698                                                                break;
1699                                                        }
1700
1701                                                        // handle status history
1702                                                        CARField fieldStatus(schemaInsideId,7); // get status field
1703                                                        string enumValue;
1704                                                        if (fieldStatus.Exists())
1705                                                        {
1706                                                                int iEnumId = atoi(enumId);
1707                                                                enumValue = GetFieldEnumValue(schemaInsideId, fieldStatus.GetInsideId(), iEnumId);
1708                                                        }
1709
1710                                                        strmTmp << ".";
1711                                                        if (enumValue.empty())
1712                                                                strmTmp << enumId;
1713                                                        else
1714                                                                strmTmp << enumValue;
1715                                                        strmTmp << "." << usrOrTimeStr;
1716                                                }
1717                                                strmTmp << "$";
1718                                                ++curPos; // skip the $ so it isnt found again
1719                                        }
1720                                        else if (fieldId[0] == '-' && iFieldId <= 0)
1721                                        {
1722                                                // keyword handling
1723                                                int iKeyword = abs(iFieldId);
1724                                                strmTmp << CAREnum::Keyword(iKeyword) << "$";
1725                                                ++curPos; // skip the $ so it isnt found again
1726                                        }
1727                                        break;
1728                                }
1729                                break;
1730                        }
1731                        if (curPos < startPos)
1732                                strmTmp << inText.substr(curPos,startPos - curPos);
1733                }
1734                if (curPos < maxLen)
1735                        strmTmp << inText.substr(curPos,maxLen - curPos);
1736
1737                //write the current string back to inText, then clear the stream for use with the application code
1738                inText = strmTmp.str();
1739                strmTmp.clear();
1740                strmTmp.str("");
1741
1742                // check for special run-process commands
1743                bool specialFound = false;
1744                string::size_type cmdStartPos = inText.find("Application-");
1745                if (cmdStartPos != string::npos)
1746                {
1747                        string::size_type nextSearchPos = cmdStartPos + 12; // add length("Application-")
1748                        specialFound = true;
1749
1750                        if (inText.compare(nextSearchPos, 17, "Copy-Field-Value ") == 0)
1751                        {
1752                                strmTmp << processTwoFields("Application-Copy-Field-Value", inText, schemaInsideId, rootLevel, refItem);
1753                        }
1754                        else if (inText.compare(nextSearchPos, 13, "Delete-Entry ") == 0)
1755                        {
1756                                strmTmp << processForm("Application-Delete-Entry", inText, schemaInsideId, rootLevel, refItem);
1757                        }
1758                        else if (inText.compare(nextSearchPos, 12, "Format-Qual ") == 0)
1759                        {
1760                                strmTmp << processForm("Application-Format-Qual", inText, schemaInsideId, rootLevel, refItem);
1761                        }
1762                        else if (inText.compare(nextSearchPos, 19, "Format-Qual-Filter ") == 0)
1763                        {
1764                                strmTmp << processForm("Application-Format-Qual-Filter", inText, schemaInsideId, rootLevel, refItem);
1765                        }
1766                        else if (inText.compare(nextSearchPos, 15, "Format-Qual-ID ") == 0)
1767                        {
1768                                strmTmp << processForm("Application-Format-Qual-ID", inText, schemaInsideId, rootLevel, refItem);
1769                        }
1770                        else if (inText.compare(nextSearchPos, 14, "Format-Qual-L ") == 0)
1771                        {
1772                                strmTmp << processForm("Application-Format-Qual-L", inText, schemaInsideId, rootLevel, refItem);
1773                        }
1774                        else if (inText.compare(nextSearchPos, 18, "Get-Approval-Join ") == 0)
1775                        {
1776                                strmTmp << processForm("Application-Get-Approval-Join", inText, schemaInsideId, rootLevel, refItem);
1777                        }
1778                        else if (inText.compare(nextSearchPos, 19, "Get-Approval-Join2 ") == 0)
1779                        {
1780                                strmTmp << processForm("Application-Get-Approval-Join2", inText, schemaInsideId, rootLevel, refItem);
1781                        }
1782                        else if (inText.compare(nextSearchPos, 16, "Get-DetSig-Join ") == 0)
1783                        {
1784                                strmTmp << processForm("Application-Get-DetSig-Join", inText, schemaInsideId, rootLevel, refItem);
1785                        }
1786                        else if (inText.compare(nextSearchPos, 17, "Get-DetSig-Join2 ") == 0)
1787                        {
1788                                strmTmp << processForm("Application-Get-DetSig-Join2", inText, schemaInsideId, rootLevel, refItem);
1789                        }
1790                        else if (inText.compare(nextSearchPos, 15, "Get-Form-Alias ") == 0)
1791                        {
1792                                strmTmp << processForm("Application-Get-Form-Alias", inText, schemaInsideId, rootLevel, refItem);
1793                        }
1794                        else if (inText.compare(nextSearchPos, 17, "Get-Locale-VuiID ") == 0)
1795                        {
1796                                strmTmp << processForm("Application-Get-Locale-VuiID", inText, schemaInsideId, rootLevel, refItem);
1797                        }
1798                        else if (inText.compare(nextSearchPos, 25, "Get-Next-Recurrence-Time ") == 0)
1799                        {
1800                                strmTmp << processForm("Application-Get-Next-Recurrence-Time", inText, schemaInsideId, rootLevel, refItem);
1801                        }
1802                        else if (inText.compare(nextSearchPos, 17, "Map-Ids-To-Names ") == 0)
1803                        {
1804                                strmTmp << processForm("Application-Map-Ids-To-Names", inText, schemaInsideId, rootLevel, refItem);
1805                        }
1806                        else if (inText.compare(nextSearchPos, 19, "Map-Ids-To-Names-L ") == 0)
1807                        {
1808                                strmTmp << processForm("Application-Map-Ids-To-Names-L", inText, schemaInsideId, rootLevel, refItem);
1809                        }
1810                        else if (inText.compare(nextSearchPos, 17, "Map-Names-To-Ids ") == 0)
1811                        {
1812                                strmTmp << processForm("Application-Map-Names-To-Ids", inText, schemaInsideId, rootLevel, refItem);
1813                        }
1814                        else if (inText.compare(nextSearchPos, 19, "Map-Names-To-Ids-L ") == 0)
1815                        {
1816                                strmTmp << processForm("Application-Map-Names-To-Ids-L", inText, schemaInsideId, rootLevel, refItem);
1817                        }
1818                        else if (inText.compare(nextSearchPos, 11, "Parse-Qual ") == 0)
1819                        {
1820                                strmTmp << processForm("Application-Parse-Qual", inText, schemaInsideId, rootLevel, refItem);
1821                        }
1822                        else if (inText.compare(nextSearchPos, 18, "Parse-Qual-Filter ") == 0)
1823                        {
1824                                strmTmp << processForm("Application-Parse-Qual-Filter", inText, schemaInsideId, rootLevel, refItem);
1825                        }
1826                        else if (inText.compare(nextSearchPos, 13, "Parse-Qual-L ") == 0)
1827                        {
1828                                strmTmp << processForm("Application-Parse-Qual-L", inText, schemaInsideId, rootLevel, refItem);
1829                        }
1830                        else if (inText.compare(nextSearchPos, 20, "Parse-Qual-SField-L ") == 0)
1831                        {
1832                                strmTmp << processForm("Application-Parse-Qual-SField-L", inText, schemaInsideId, rootLevel, refItem);
1833                        }
1834                        else if (inText.compare(nextSearchPos, 17, "Parse-Val-SField ") == 0)
1835                        {
1836                                strmTmp << processForm("Application-Parse-Val-SField", inText, schemaInsideId, rootLevel, refItem);
1837                        }
1838                        else if (inText.compare(nextSearchPos, 19, "Query-Delete-Entry ") == 0)
1839                        {
1840                                strmTmp << processForm("Application-Query-Delete-Entry", inText, schemaInsideId, rootLevel, refItem);
1841                        }
1842                        else
1843                        {
1844                                specialFound = false;
1845                        }
1846                }
1847               
1848                cmdStartPos = inText.find("PERFORM-ACTION-");
1849                if (cmdStartPos != string::npos)
1850                {
1851                        string::size_type nextSearchPos = cmdStartPos + 15; // add length("PERFORM-ACTION-")
1852                        specialFound = true;
1853
1854                        if (inText.compare(nextSearchPos, 12, "ACTIVE-LINK ") == 0)
1855                        {
1856                                strmTmp << processSecondParameter("PERFORM-ACTION-ACTIVE-LINK", inText, schemaInsideId, rootLevel, refItem);
1857                        }
1858                        else if (inText.compare(nextSearchPos, 15, "ADD-ATTACHMENT ") == 0)
1859                        {
1860                                strmTmp << processOneField("PERFORM-ACTION-ADD-ATTACHMENT", inText, schemaInsideId, rootLevel, refItem);
1861                        }
1862                        else if (inText.compare(nextSearchPos, 18, "DELETE-ATTACHMENT ") == 0)
1863                        {
1864                                strmTmp << processOneField("PERFORM-ACTION-DELETE-ATTACHMENT", inText, schemaInsideId, rootLevel, refItem);
1865                        }
1866                        else if (inText.compare(nextSearchPos, 16, "GET-FIELD-LABEL ") == 0)
1867                        {
1868                                strmTmp << processOneField("PERFORM-ACTION-GET-FIELD-LABEL", inText, schemaInsideId, rootLevel, refItem);
1869                        }
1870                        else if (inText.compare(nextSearchPos, 15, "GET-PREFERENCE ") == 0)
1871                        {
1872                                strmTmp << processOneField("PERFORM-ACTION-GET-PREFERENCE", inText, schemaInsideId, rootLevel, refItem);
1873                        }
1874                        else if (inText.compare(nextSearchPos, 28, "NAV-FIELD-SET-SELECTED-ITEM ") == 0)
1875                        {
1876                                strmTmp << processOneField("PERFORM-ACTION-NAV-FIELD-SET-SELECTED-ITEM", inText, schemaInsideId, rootLevel, refItem);
1877                        }
1878                        else if (inText.compare(nextSearchPos, 16, "OPEN-ATTACHMENT ") == 0)
1879                        {
1880                                strmTmp << processOneField("PERFORM-ACTION-OPEN-ATTACHMENT", inText, schemaInsideId, rootLevel, refItem);
1881                        }
1882                        else if (inText.compare(nextSearchPos, 16, "SAVE-ATTACHMENT ") == 0)
1883                        {
1884                                strmTmp << processOneField("PERFORM-ACTION-SAVE-ATTACHMENT", inText, schemaInsideId, rootLevel, refItem);
1885                        }
1886                        else if (inText.compare(nextSearchPos, 15, "SET-PREFERENCE ") == 0)
1887                        {
1888                                strmTmp << processOneField("PERFORM-ACTION-SET-PREFERENCE", inText, schemaInsideId, rootLevel, refItem);
1889                        }
1890                        else if (inText.compare(nextSearchPos, 12, "TABLE-CLEAR ") == 0)
1891                        {
1892                                strmTmp << processOneField("PERFORM-ACTION-TABLE-CLEAR", inText, schemaInsideId, rootLevel, refItem);
1893                        }
1894                        else if (inText.compare(nextSearchPos, 23, "TABLE-CLEAR-ROWCHANGED ") == 0)
1895                        {
1896                                strmTmp << processOneField("PERFORM-ACTION-TABLE-CLEAR-ROWCHANGED", inText, schemaInsideId, rootLevel, refItem);
1897                        }
1898                        else if (inText.compare(nextSearchPos, 18, "TABLE-DESELECTALL ") == 0)
1899                        {
1900                                strmTmp << processOneField("PERFORM-ACTION-TABLE-DESELECTALL", inText, schemaInsideId, rootLevel, refItem);
1901                        }
1902                        else if (inText.compare(nextSearchPos, 26, "TABLE-GET-SELECTED-COLUMN ") == 0)
1903                        {
1904                                strmTmp << processOneField("PERFORM-ACTION-TABLE-GET-SELECTED-COLUMN", inText, schemaInsideId, rootLevel, refItem);
1905                        }
1906                        else if (inText.compare(nextSearchPos, 23, "TABLE-IS-LEAF-SELECTED ") == 0)
1907                        {
1908                                strmTmp << processOneField("PERFORM-ACTION-TABLE-IS-LEAF-SELECTED", inText, schemaInsideId, rootLevel, refItem);
1909                        }
1910                        else if (inText.compare(nextSearchPos, 17, "TABLE-NEXT-CHUNK ") == 0)
1911                        {
1912                                strmTmp << processOneField("PERFORM-ACTION-TABLE-NEXT-CHUNK", inText, schemaInsideId, rootLevel, refItem);
1913                        }
1914                        else if (inText.compare(nextSearchPos, 17, "TABLE-PREV-CHUNK ") == 0)
1915                        {
1916                                strmTmp << processOneField("PERFORM-ACTION-TABLE-PREV-CHUNK", inText, schemaInsideId, rootLevel, refItem);
1917                        }
1918                        else if (inText.compare(nextSearchPos, 14, "TABLE-REFRESH ") == 0)
1919                        {
1920                                strmTmp << processOneField("PERFORM-ACTION-TABLE-REFRESH", inText, schemaInsideId, rootLevel, refItem);
1921                        }
1922                        else if (inText.compare(nextSearchPos, 13, "TABLE-REPORT ") == 0)
1923                        {
1924                                strmTmp << processOneField("PERFORM-ACTION-TABLE-REPORT", inText, schemaInsideId, rootLevel, refItem);
1925                        }
1926                        else if (inText.compare(nextSearchPos, 18, "TABLE-SELECT-NODE ") == 0)
1927                        {
1928                                strmTmp << processOneField("PERFORM-ACTION-TABLE-SELECT-NODE", inText, schemaInsideId, rootLevel, refItem);
1929                        }
1930                        else if (inText.compare(nextSearchPos, 16, "TABLE-SELECTALL ") == 0)
1931                        {
1932                                strmTmp << processOneField("PERFORM-ACTION-TABLE-SELECTALL", inText, schemaInsideId, rootLevel, refItem);
1933                        }
1934                        else
1935                        {
1936                                specialFound = false;
1937                        }
1938                }
1939
1940                return (specialFound ? strmTmp.str() : inText);
1941        }
1942        catch(exception& e)
1943        {
1944                cout << "EXCEPTION in TextFindField: " << e.what() << endl;
1945        }
1946
1947        return inText;
1948}
1949
1950string CARInside::XMLFindFields(string inText, int schemaInsideId, int rootLevel, const CRefItem *refItem)
1951{       
1952        try
1953        {
1954                if(inText.empty())
1955                        return "";
1956
1957                CARSchema schema(schemaInsideId);
1958
1959                unsigned int fieldCount = schema.GetFields()->GetCount();
1960                for(unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
1961                {
1962                        CARField field(schemaInsideId, 0, fieldIndex);
1963
1964                        stringstream strmTmp;
1965                        strmTmp << "arFieldId=&quot;" << field.GetFieldId() << "&quot;";                       
1966
1967                        stringstream fieldLink;
1968                        fieldLink << "arFieldId=&quot;" << field.GetURL(rootLevel) << "&quot;";                                 
1969
1970                        unsigned int nLengthOrg = (unsigned int)inText.length();
1971
1972                        string fField = strmTmp.str();
1973                        inText = CUtil::StrReplace(fField, fieldLink.str(), inText);
1974
1975                        //if the string is longer because we have added a link (long string) we add a field reference
1976                        if(inText.length() > nLengthOrg) 
1977                        {
1978                                AddFieldReference(schema.GetInsideId(), field.GetInsideId(), *refItem);
1979                        }
1980                }
1981        }
1982        catch(exception& e)
1983        {
1984                cout << "EXCEPTION in XMLFindField: " << e.what() << endl;
1985        }
1986
1987        return inText;
1988}
1989
1990string CARInside::ServerObjectHistory(CARServerObject *obj, int rootLevel, bool noTableDescription)
1991{               
1992        stringstream strm;
1993        strm.str("");
1994
1995        try
1996        {
1997                stringstream historyLog;
1998                if(obj->GetChangeDiary() != NULL)
1999                {                               
2000                        ARDiaryList diaryList; ARZeroMemory(&diaryList);
2001                        ARStatusList status; ARZeroMemory(&status);
2002                        if(ARDecodeDiary(&this->arControl, const_cast<char*>(obj->GetChangeDiary()), &diaryList, &status)==AR_RETURN_OK)
2003                        {
2004                                if(diaryList.numItems > 0)
2005                                {
2006                                        for(unsigned int j=0; j<diaryList.numItems; j++)
2007                                        {
2008                                                historyLog << CUtil::DateTimeToHTMLString(diaryList.diaryList[j].timeVal) << " " << this->LinkToUser(diaryList.diaryList[j].user, rootLevel) << "<br/>" << endl;
2009                                                historyLog << diaryList.diaryList[j].value << "<br/><br/>" << endl;
2010                                        }
2011                                }
2012                                else
2013                                {
2014                                        historyLog << EmptyValue << endl;
2015                                }
2016                        }
2017                        FreeARDiaryList(&diaryList, false);
2018                        FreeARStatusList(&status, false);
2019                }
2020
2021                CTable tbl("history", "TblObjectHistory");
2022                tbl.AddColumn(20, "Description");
2023                tbl.AddColumn(80, "Value");
2024
2025                if (!noTableDescription)
2026                        tbl.description = CWebUtil::ImageTag("doc.gif", rootLevel) + "Change History";
2027
2028                //Owner
2029                CTableRow tblRow("");
2030                tblRow.AddCellList(CTableCell("Owner"), CTableCell(this->LinkToUser(obj->GetOwner(), rootLevel)));
2031                tbl.AddRow(tblRow);
2032
2033                //Last changed         
2034                stringstream strmLastChanged;
2035                strmLastChanged.str("");
2036                strmLastChanged << CUtil::DateTimeToHTMLString(obj->GetTimestamp()) << " " << this->LinkToUser(obj->GetLastChanged(), rootLevel) << endl;
2037
2038                tblRow.AddCellList(CTableCell("Last changed"), CTableCell(strmLastChanged.str()));
2039                tbl.AddRow(tblRow);
2040
2041
2042                //History
2043                tblRow.AddCellList(CTableCell("History Log"), CTableCell(historyLog.str()));
2044                tbl.AddRow(tblRow);
2045
2046                //Helptext
2047                string tmpHelptext;
2048                if(obj->GetHelpText() != NULL)
2049                {
2050                        tmpHelptext = CUtil::StrReplace("\n", "<br/>", obj->GetHelpText());
2051                }
2052                else
2053                {
2054                  tmpHelptext = EmptyValue;
2055                }
2056
2057                tblRow.AddCellList(CTableCell("Helptext"), CTableCell(tmpHelptext));
2058                tbl.AddRow(tblRow);
2059
2060                strm << tbl;
2061        }
2062        catch(exception& e)
2063        {
2064                cout << "EXCEPTION writing server object history: " << e.what() << endl;
2065        }       
2066
2067        return strm.str();
2068}
2069
2070void CARInside::DoWork(int nMode)
2071{       
2072        // first step is to create directory structure
2073        Prepare();
2074
2075        // now extract resources (images, css, js and so on)
2076        ExtractResources();
2077
2078        // now load the object either from server or from file
2079        LoadServerObjects(nMode);
2080
2081        // now create navigation page based on supported server features
2082        { CNavigationPage navPage(appConfig); navPage.Write(); }
2083
2084        // build needed reference tables
2085        CScanMain::BuildReferences();
2086
2087        // write documentation
2088        Documentation();
2089}
2090
2091void CARInside::ParseVersionString(string version)
2092{
2093        char ver[40];
2094        int part = 0;
2095
2096        vMajor = 0;
2097        vMinor = 0;
2098        vRevision = 0;
2099
2100        unsigned int verPos=0;
2101        unsigned int verStart=0;
2102        for (; verPos < version.size(); ++verPos)
2103        {
2104                char c = version.at(verPos);
2105                if (c >= '0' && c <= '9' ) 
2106                {
2107                        ver[verPos] = c;
2108                        continue;
2109                }
2110                if (verPos > verStart)
2111                {
2112                        ver[verPos] = 0;
2113                        int num = atoi(&ver[verStart]);
2114                        switch (part)
2115                        {
2116                        case 0:
2117                                vMajor = num;
2118                                break;
2119                        case 1:
2120                                vMinor = num;
2121                                break;
2122                        case 2:
2123                                vRevision = num;
2124                                break;
2125                        }
2126                        ++part;
2127                        verStart = verPos + 1;
2128                }
2129                if (c != '.') break;
2130        }
2131        ver[verPos] = 0;
2132}
2133
2134void CARInside::ParseVersionString(int xmlVersion)
2135{
2136        if (xmlVersion <= arXmlVersion) return;
2137
2138        if (xmlVersion >= AR_XML_VERSION_750)
2139        {
2140                arServerVersion = "7.5.00";
2141                vMajor = 7; vMinor = 5; vRevision = 0;
2142        }
2143        else if (xmlVersion >= AR_XML_VERSION_710)
2144        {
2145                arServerVersion = "7.1.00";
2146                vMajor = 7; vMinor = 1; vRevision = 0;
2147        }
2148        else if (xmlVersion >= AR_XML_VERSION_700)
2149        {
2150                arServerVersion = "7.0.00";
2151                vMajor = 7; vMinor = 0; vRevision = 0;
2152        }
2153        else if (xmlVersion >= AR_XML_VERSION_710)
2154        {
2155                arServerVersion = "7.1.00";
2156                vMajor = 7; vMinor = 1; vRevision = 0;
2157        }
2158        else if (xmlVersion >= AR_XML_VERSION_710)
2159        {
2160                arServerVersion = "7.1.00";
2161                vMajor = 7; vMinor = 1; vRevision = 0;
2162        }
2163        else if (xmlVersion >= AR_XML_VERSION_600)
2164        {
2165                // 6.0 and 6.3 use the same export version number. To show keywords
2166                // and other things (in case of a 6.3 export file) correctly, the
2167                // version is set to 6.3
2168                arServerVersion = "6.03.00";
2169                vMajor = 6; vMinor = 3; vRevision = 0;
2170        }
2171        else if (xmlVersion >= AR_XML_VERSION_510)
2172        {
2173                arServerVersion = "5.1.00";
2174                vMajor = 5; vMinor = 1; vRevision = 0;
2175        }
2176        else if (xmlVersion >= AR_XML_VERSION_500)
2177        {
2178                arServerVersion = "5.0.00";
2179                vMajor = 5; vMinor = 0; vRevision = 0;
2180        }
2181        else if (xmlVersion >= AR_XML_VERSION_450)
2182        {
2183                arServerVersion = "4.5.00";
2184                vMajor = 4; vMinor = 5; vRevision = 0;
2185        }
2186}
2187
2188int CARInside::CompareServerVersion(int major, int minor, int revision)
2189{
2190        if (vMajor == major)
2191        {
2192                if (minor > -1)
2193                {
2194                        if (vMinor == minor)
2195                        {
2196                                if (revision > -1)
2197                                {
2198                                        if (vRevision == revision) return 0;
2199                                        if (vRevision < revision) return -1;
2200                                        if (vRevision > revision) return 1;
2201                                }
2202                                return 0;
2203                        }
2204                        if (vMinor < minor) return -1;
2205                        if (vMinor > minor) return 1;
2206                }
2207                return 0;
2208        }
2209        if (vMajor < major) return -1;
2210        /*if (vMajor > major)*/ return 1;
2211}
2212
2213string CARInside::processOneField(const string& command, const string& inText, int schemaInsideId, int rootLevel, const CRefItem *refItem)
2214{
2215        stringstream strmTmp;
2216        int fieldId = 0;
2217        size_t length = command.length()+1;
2218        size_t pos = inText.find(command);
2219
2220        //put the command into the stream
2221        strmTmp << inText.substr(0,(length+pos));
2222        //get everything after the command
2223        string tmp = inText.substr(length+pos);
2224        //get position of next space
2225        pos = tmp.find(" ");
2226
2227        //set the fieldID = to the one we found
2228
2229        if (pos != std::string::npos)
2230                fieldId = atoi(tmp.substr(0,pos).c_str());
2231        else
2232                fieldId = atoi(tmp.c_str());
2233
2234        if (fieldId != std::string::npos && fieldId > 0)
2235                strmTmp << refFieldID(fieldId, schemaInsideId, rootLevel, refItem);
2236
2237        if (pos != std::string::npos)
2238        {
2239                tmp = tmp.substr(pos,tmp.length());
2240                strmTmp << tmp;
2241        }
2242
2243        return strmTmp.str();
2244}
2245string CARInside::processTwoFields(const string& command, const string& inText, int schemaInsideId, int rootLevel, const CRefItem *refItem)
2246{
2247        stringstream strmTmp;
2248        int fieldId = 0;
2249        size_t length = command.length()+1;
2250        size_t pos = inText.find(command);
2251
2252        //put the command into the stream
2253        strmTmp << inText.substr(0,(length+pos));
2254        //get everything after the command
2255        string tmp = inText.substr(length+pos);
2256        if (tmp.find("$") == 0 && tmp.find("$") != std::string::npos)
2257        {
2258                tmp = tmp.substr(1);
2259                pos = tmp.find("$")+1;
2260                strmTmp << "$" << tmp.substr(0,pos);
2261        }
2262        else
2263        {
2264                pos = tmp.find(" ");
2265                fieldId = atoi(tmp.substr(0,pos).c_str());
2266                strmTmp << refFieldID(fieldId, schemaInsideId, rootLevel, refItem);
2267        }
2268
2269        //put a space between the field ID's
2270        strmTmp << " ";
2271
2272        //get position of next space
2273        pos = tmp.find(" ");
2274        //get everything after the space
2275        tmp = tmp.substr(pos+1);
2276
2277        if (tmp.find("$") == 0 && tmp.find("$") != std::string::npos)
2278        {
2279                strmTmp << tmp;
2280        }
2281        else
2282        {
2283                fieldId = atoi(tmp.c_str());
2284                strmTmp << refFieldID(fieldId, schemaInsideId, rootLevel, refItem);
2285        }
2286
2287        return strmTmp.str();
2288}
2289string CARInside::processForm(const string& command, const string& inText, int schemaInsideId, int rootLevel, const CRefItem *refItem)
2290{
2291        stringstream strmTmp;
2292        string form = "";
2293        size_t length = command.length()+1;
2294        size_t pos = inText.find(command);
2295
2296        //put the command into the stream
2297        strmTmp << inText.substr(0,(length+pos));
2298        //get everything after the command
2299        string tmp = inText.substr(length+pos);
2300        //ok, we are at the first parameter, need to first find if it starts with a "
2301        if (tmp.substr(0,1) == "\"")
2302        {
2303                strmTmp << "\"";
2304                pos = tmp.find("\"",1);
2305                form = tmp.substr(1,pos-1);
2306        }
2307        else
2308        {
2309                //get position of next space
2310                pos = tmp.find(" ");
2311                form = tmp.substr(0,pos);
2312        }
2313        //generate link for form
2314        CARSchema schema(form);
2315        if (schema.Exists())
2316                strmTmp << schema.GetURL(rootLevel, false);
2317        else
2318                strmTmp << form;
2319                //AddReferenceItem(refItem);
2320
2321        //write anything past the form to output
2322        strmTmp << tmp.substr(pos);
2323
2324        return strmTmp.str();
2325}
2326string CARInside::processSecondParameter(const string& command, const string& inText, int schemaInsideId, int rootLevel, const CRefItem *refItem)
2327{
2328        stringstream strmTmp;
2329        int fieldId = 0;
2330        size_t length = command.length()+1;
2331        size_t pos = inText.find(command);
2332
2333        //put the command into the stream
2334        strmTmp << inText.substr(0,(length+pos));
2335        //get everything after the command
2336        string tmp = inText.substr(length+pos);
2337        //get position of next space
2338        pos = tmp.find(" ");
2339        //set the fieldID = to the one we found
2340        strmTmp << tmp.substr(0,pos);
2341        //put a space in there
2342        strmTmp << " ";
2343        //get position of next space
2344        pos = tmp.find(" ");
2345        //get everything after the space
2346        if (pos != std::string::npos)
2347        {
2348                tmp = tmp.substr(pos);
2349                //set the fieldID = to the one we found
2350                fieldId = atoi(tmp.c_str());
2351                strmTmp << refFieldID(fieldId, schemaInsideId, rootLevel, refItem) << endl;
2352        }
2353
2354        return strmTmp.str();
2355}
2356bool CARInside::getPos(const string& inText, const string& findText)
2357{
2358        size_t pos = inText.find(findText);
2359        return (pos != std::string::npos);
2360}
2361
2362string CARInside::refFieldID(int iFieldId, int schemaInsideId, int rootLevel, const CRefItem *refItem)
2363{
2364        stringstream strmTmp;
2365
2366        //add the reference
2367        try {
2368                CARField field(schemaInsideId, iFieldId);
2369                if (field.Exists())
2370                {
2371                        strmTmp << field.GetURL(rootLevel);
2372                }
2373                else
2374                        strmTmp << iFieldId;
2375
2376                // add reference
2377                AddFieldReference(schemaInsideId, iFieldId, *refItem);
2378        }
2379        catch (...) {
2380                cout << "Exception in refFieldID" << endl;
2381        }
2382
2383        return strmTmp.str();
2384}
2385
2386#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
2387int CARInside::LoadImages()
2388{
2389        imageList.LoadFromServer();
2390        imageList.Sort();
2391        return imageList.GetCount();
2392}
2393
2394string CARInside::LinkToImage(unsigned int imageIndex, int rootLevel)
2395{
2396        CARImage image(imageIndex);
2397        if (image.Exists())
2398        {
2399                return image.GetURL(rootLevel);
2400        }
2401        return EmptyValue;
2402}
2403
2404string CARInside::LinkToImage(const string &imageName, int rootLevel)
2405{
2406        int imageIndex = imageList.FindImage(imageName.c_str());
2407        if (imageIndex < 0)
2408        {
2409                return "<span class=\"fieldNotFound\">" + imageName + "</span>";
2410        }
2411        else
2412        {
2413                return LinkToImage(imageIndex, rootLevel);
2414        }
2415}
2416#endif // AR_CURRENT_API_VERSION >= AR_API_VERSION_750
2417
2418bool CARInside::WriteHTAccess()
2419{
2420        stringstream strm;
2421        strm << this->appConfig.targetFolder << "/" << ".htaccess";
2422
2423        if (FileExists(strm.str()))
2424                return true;            // if file is already there, it should be configured correctly
2425
2426        try
2427        {
2428                string fileName = strm.str();
2429                LOG << "Save file '" << fileName;
2430
2431                ofstream fout(fileName.c_str(), ios::out);
2432                fout << "RemoveType .gz" << endl << "AddEncoding gzip .gz";
2433                fout.close();
2434        }
2435        catch (exception &e)
2436        {
2437                stringstream erStrm;
2438                erStrm << "Error saving file '" << strm.str() << "' to disk. Error: " << e.what();
2439                throw(AppException(erStrm.str(), "undefined", "FileIo"));
2440        }
2441        return true;
2442}
2443
2444void CARInside::SetupOverlaySupport()
2445{
2446#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
2447        if (CompareServerVersion(7,6,4) >= 0 && appConfig.bOverlaySupport)
2448        {
2449                ARStatusList status; ARZeroMemory(&status);
2450                ARValueStruct value;
2451                value.dataType = AR_DATA_TYPE_CHAR;
2452                value.u.charVal = (char*)AR_OVERLAY_CLIENT_MODE_FULL;
2453                if (ARSetSessionConfiguration(&arControl, AR_SESS_CONTROL_PROP_API_OVERLAYGROUP, &value, &status) != AR_RETURN_OK)
2454                        cerr << "SetSessionConfiguration failed: " << BuildMessageAndFreeStatus(status);
2455        }
2456#endif
2457}
2458
2459void CARInside::ExtractResources()
2460{
2461        try
2462        {
2463                ResourceFileLocatorAndExtractor resExtractor("arires.tgz");
2464                resExtractor.ExtractTo(appConfig.targetFolder);
2465        }
2466        catch (std::exception &ex)
2467        {
2468                cerr << "Error while extracting resources: " << ex.what() << endl;
2469        }
2470}
Note: See TracBrowser for help on using the repository browser.