1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include "install-ds.h"
6 #include <prmem.h>
7 #include <plstr.h>
8 #include <prprf.h>
9 #include <string.h>
10 
11 #define PORT_Strcasecmp PL_strcasecmp
12 
13 #define MODULE_FILE_STRING "ModuleFile"
14 #define MODULE_NAME_STRING "ModuleName"
15 #define MECH_FLAGS_STRING "DefaultMechanismFlags"
16 #define CIPHER_FLAGS_STRING "DefaultCipherFlags"
17 #define FILES_STRING "Files"
18 #define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
19 #define PLATFORMS_STRING "Platforms"
20 #define RELATIVE_DIR_STRING "RelativePath"
21 #define ABSOLUTE_DIR_STRING "AbsolutePath"
22 #define FILE_PERMISSIONS_STRING "FilePermissions"
23 #define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
24 #define EXECUTABLE_STRING "Executable"
25 
26 #define DEFAULT_PERMISSIONS 0777
27 
28 #define PLATFORM_SEPARATOR_CHAR ':'
29 
30 /* Error codes */
31 enum {
32     BOGUS_RELATIVE_DIR = 0,
33     BOGUS_ABSOLUTE_DIR,
34     BOGUS_FILE_PERMISSIONS,
35     NO_RELATIVE_DIR,
36     NO_ABSOLUTE_DIR,
37     EMPTY_PLATFORM_STRING,
38     BOGUS_PLATFORM_STRING,
39     REPEAT_MODULE_FILE,
40     REPEAT_MODULE_NAME,
41     BOGUS_MODULE_FILE,
42     BOGUS_MODULE_NAME,
43     REPEAT_MECH,
44     BOGUS_MECH_FLAGS,
45     REPEAT_CIPHER,
46     BOGUS_CIPHER_FLAGS,
47     REPEAT_FILES,
48     REPEAT_EQUIV,
49     BOGUS_EQUIV,
50     EQUIV_TOO_MUCH_INFO,
51     NO_FILES,
52     NO_MODULE_FILE,
53     NO_MODULE_NAME,
54     NO_PLATFORMS,
55     EQUIV_LOOP,
56     UNKNOWN_MODULE_FILE
57 };
58 
59 /* Indexed by the above error codes */
60 static const char* errString[] = {
61     "%s: Invalid relative directory",
62     "%s: Invalid absolute directory",
63     "%s: Invalid file permissions",
64     "%s: No relative directory specified",
65     "%s: No absolute directory specified",
66     "Empty string given for platform name",
67     "%s: invalid platform string",
68     "More than one ModuleFile entry given for platform %s",
69     "More than one ModuleName entry given for platform %s",
70     "Invalid ModuleFile specification for platform %s",
71     "Invalid ModuleName specification for platform %s",
72     "More than one DefaultMechanismFlags entry given for platform %s",
73     "Invalid DefaultMechanismFlags specification for platform %s",
74     "More than one DefaultCipherFlags entry given for platform %s",
75     "Invalid DefaultCipherFlags entry given for platform %s",
76     "More than one Files entry given for platform %s",
77     "More than one EquivalentPlatform entry given for platform %s",
78     "Invalid EquivalentPlatform specification for platform %s",
79     "Module %s uses an EquivalentPlatform but also specifies its own"
80     " information",
81     "No Files specification in module %s",
82     "No ModuleFile specification in module %s",
83     "No ModuleName specification in module %s",
84     "No Platforms specification in installer script",
85     "Platform %s has an equivalency loop",
86     "Module file \"%s\" in platform \"%s\" does not exist"
87 };
88 
89 static char* PR_Strdup(const char* str);
90 
91 #define PAD(x)                  \
92     {                           \
93         int i;                  \
94         for (i = 0; i < x; i++) \
95             printf(" ");        \
96     }
97 #define PADINC 4
98 
99 Pk11Install_File*
Pk11Install_File_new()100 Pk11Install_File_new()
101 {
102     Pk11Install_File* new_this;
103     new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
104     Pk11Install_File_init(new_this);
105     return new_this;
106 }
107 
108 void
Pk11Install_File_init(Pk11Install_File * _this)109 Pk11Install_File_init(Pk11Install_File* _this)
110 {
111     _this->jarPath = NULL;
112     _this->relativePath = NULL;
113     _this->absolutePath = NULL;
114     _this->executable = PR_FALSE;
115     _this->permissions = 0;
116 }
117 
118 /*
119 //////////////////////////////////////////////////////////////////////////
120 // Method:  ~Pk11Install_File
121 // Class:   Pk11Install_File
122 // Notes:   Destructor.
123 */
124 void
Pk11Install_File_delete(Pk11Install_File * _this)125 Pk11Install_File_delete(Pk11Install_File* _this)
126 {
127     Pk11Install_File_Cleanup(_this);
128 }
129 
130 /*
131 //////////////////////////////////////////////////////////////////////////
132 // Method:  Cleanup
133 // Class:   Pk11Install_File
134 */
135 void
Pk11Install_File_Cleanup(Pk11Install_File * _this)136 Pk11Install_File_Cleanup(Pk11Install_File* _this)
137 {
138     if (_this->jarPath) {
139         PR_Free(_this->jarPath);
140         _this->jarPath = NULL;
141     }
142     if (_this->relativePath) {
143         PR_Free(_this->relativePath);
144         _this->relativePath = NULL;
145     }
146     if (_this->absolutePath) {
147         PR_Free(_this->absolutePath);
148         _this->absolutePath = NULL;
149     }
150 
151     _this->permissions = 0;
152     _this->executable = PR_FALSE;
153 }
154 
155 /*
156 //////////////////////////////////////////////////////////////////////////
157 // Method:  Generate
158 // Class:   Pk11Install_File
159 // Notes:   Creates a file data structure from a syntax tree.
160 // Returns: NULL for success, otherwise an error message.
161 */
162 char*
Pk11Install_File_Generate(Pk11Install_File * _this,const Pk11Install_Pair * pair)163 Pk11Install_File_Generate(Pk11Install_File* _this,
164                           const Pk11Install_Pair* pair)
165 {
166     Pk11Install_ListIter* iter;
167     Pk11Install_Value* val;
168     Pk11Install_Pair* subpair;
169     Pk11Install_ListIter* subiter;
170     Pk11Install_Value* subval;
171     char* errStr;
172     char* endp;
173     PRBool gotPerms;
174 
175     iter = NULL;
176     subiter = NULL;
177     errStr = NULL;
178     gotPerms = PR_FALSE;
179 
180     /* Clear out old values */
181     Pk11Install_File_Cleanup(_this);
182 
183     _this->jarPath = PR_Strdup(pair->key);
184 
185     /* Go through all the pairs under this file heading */
186     iter = Pk11Install_ListIter_new(pair->list);
187     for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
188         if (val->type == PAIR_VALUE) {
189             subpair = val->pair;
190 
191             /* Relative directory */
192             if (!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
193                 subiter = Pk11Install_ListIter_new(subpair->list);
194                 subval = subiter->current;
195                 if (!subval || (subval->type != STRING_VALUE)) {
196                     errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR],
197                                          _this->jarPath);
198                     goto loser;
199                 }
200                 _this->relativePath = PR_Strdup(subval->string);
201                 Pk11Install_ListIter_delete(&subiter);
202 
203                 /* Absolute directory */
204             } else if (!PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
205                 subiter = Pk11Install_ListIter_new(subpair->list);
206                 subval = subiter->current;
207                 if (!subval || (subval->type != STRING_VALUE)) {
208                     errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR],
209                                          _this->jarPath);
210                     goto loser;
211                 }
212                 _this->absolutePath = PR_Strdup(subval->string);
213                 Pk11Install_ListIter_delete(&subiter);
214 
215                 /* file permissions */
216             } else if (!PORT_Strcasecmp(subpair->key,
217                                         FILE_PERMISSIONS_STRING)) {
218                 subiter = Pk11Install_ListIter_new(subpair->list);
219                 subval = subiter->current;
220                 if (!subval || (subval->type != STRING_VALUE) ||
221                     !subval->string || !subval->string[0]) {
222                     errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
223                                          _this->jarPath);
224                     goto loser;
225                 }
226                 _this->permissions = (int)strtol(subval->string, &endp, 8);
227                 if (*endp != '\0') {
228                     errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
229                                          _this->jarPath);
230                     goto loser;
231                 }
232                 gotPerms = PR_TRUE;
233                 Pk11Install_ListIter_delete(&subiter);
234             }
235         } else {
236             if (!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
237                 _this->executable = PR_TRUE;
238             }
239         }
240     }
241 
242     /* Default permission value */
243     if (!gotPerms) {
244         _this->permissions = DEFAULT_PERMISSIONS;
245     }
246 
247     /* Make sure we got all the information */
248     if (!_this->relativePath && !_this->absolutePath) {
249         errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
250         goto loser;
251     }
252 #if 0
253     if(!_this->relativePath ) {
254         errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
255         goto loser;
256     }
257     if(!_this->absolutePath) {
258         errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
259         goto loser;
260     }
261 #endif
262 
263 loser:
264     if (iter) {
265         Pk11Install_ListIter_delete(&iter);
266     }
267     if (subiter) {
268         Pk11Install_ListIter_delete(&subiter);
269     }
270     return errStr;
271 }
272 
273 /*
274 //////////////////////////////////////////////////////////////////////////
275 // Method:  Print
276 // Class:   Pk11Install_File
277 */
278 void
Pk11Install_File_Print(Pk11Install_File * _this,int pad)279 Pk11Install_File_Print(Pk11Install_File* _this, int pad)
280 {
281     PAD(pad);
282     printf("jarPath: %s\n",
283            _this->jarPath ? _this->jarPath : "<NULL>");
284     PAD(pad);
285     printf("relativePath: %s\n",
286            _this->relativePath ? _this->relativePath : "<NULL>");
287     PAD(pad);
288     printf("absolutePath: %s\n",
289            _this->absolutePath ? _this->absolutePath : "<NULL>");
290     PAD(pad);
291     printf("permissions: %o\n", _this->permissions);
292 }
293 
294 Pk11Install_PlatformName*
Pk11Install_PlatformName_new()295 Pk11Install_PlatformName_new()
296 {
297     Pk11Install_PlatformName* new_this;
298     new_this = (Pk11Install_PlatformName*)
299         PR_Malloc(sizeof(Pk11Install_PlatformName));
300     Pk11Install_PlatformName_init(new_this);
301     return new_this;
302 }
303 
304 void
Pk11Install_PlatformName_init(Pk11Install_PlatformName * _this)305 Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
306 {
307     _this->OS = NULL;
308     _this->verString = NULL;
309     _this->numDigits = 0;
310     _this->arch = NULL;
311 }
312 
313 /*
314 //////////////////////////////////////////////////////////////////////////
315 // Method:  ~Pk11Install_PlatformName
316 // Class:   Pk11Install_PlatformName
317 */
318 void
Pk11Install_PlatformName_delete(Pk11Install_PlatformName * _this)319 Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
320 {
321     Pk11Install_PlatformName_Cleanup(_this);
322 }
323 
324 /*
325 //////////////////////////////////////////////////////////////////////////
326 // Method:  Cleanup
327 // Class:   Pk11Install_PlatformName
328 */
329 void
Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName * _this)330 Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
331 {
332     if (_this->OS) {
333         PR_Free(_this->OS);
334         _this->OS = NULL;
335     }
336     if (_this->verString) {
337         int i;
338         for (i = 0; i < _this->numDigits; i++) {
339             PR_Free(_this->verString[i]);
340         }
341         PR_Free(_this->verString);
342         _this->verString = NULL;
343     }
344     if (_this->arch) {
345         PR_Free(_this->arch);
346         _this->arch = NULL;
347     }
348     _this->numDigits = 0;
349 }
350 
351 /*
352 //////////////////////////////////////////////////////////////////////////
353 // Method:  Generate
354 // Class:   Pk11Install_PlatformName
355 // Notes:   Extracts the information from a platform string.
356 */
357 char*
Pk11Install_PlatformName_Generate(Pk11Install_PlatformName * _this,const char * str)358 Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
359                                   const char* str)
360 {
361     char* errStr;
362     char* copy;
363     char *end, *start;   /* start and end of a section (OS, version, arch)*/
364     char *pend, *pstart; /* start and end of one portion of version*/
365     char* endp;          /* used by strtol*/
366     int periods, i;
367 
368     errStr = NULL;
369     copy = NULL;
370 
371     if (!str) {
372         errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
373         goto loser;
374     }
375     copy = PR_Strdup(str);
376 
377     /*
378     // Get the OS
379     */
380     end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
381     if (!end || end == copy) {
382         errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
383         goto loser;
384     }
385     *end = '\0';
386 
387     _this->OS = PR_Strdup(copy);
388 
389     /*
390     // Get the digits of the version of form: x.x.x (arbitrary number of digits)
391     */
392 
393     start = end + 1;
394     end = strchr(start, PLATFORM_SEPARATOR_CHAR);
395     if (!end) {
396         errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
397         goto loser;
398     }
399     *end = '\0';
400 
401     if (end != start) {
402         /* Find out how many periods*/
403         periods = 0;
404         pstart = start;
405         while ((pend = strchr(pstart, '.'))) {
406             periods++;
407             pstart = pend + 1;
408         }
409         _this->numDigits = 1 + periods;
410         _this->verString = (char**)PR_Malloc(sizeof(char*) * _this->numDigits);
411 
412         pstart = start;
413         i = 0;
414         /* Get the digits before each period*/
415         while ((pend = strchr(pstart, '.'))) {
416             if (pend == pstart) {
417                 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
418                 goto loser;
419             }
420             *pend = '\0';
421             _this->verString[i] = PR_Strdup(pstart);
422             endp = pend;
423             if (endp == pstart || (*endp != '\0')) {
424                 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
425                 goto loser;
426             }
427             pstart = pend + 1;
428             i++;
429         }
430         /* Last digit comes after the last period*/
431         if (*pstart == '\0') {
432             errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
433             goto loser;
434         }
435         _this->verString[i] = PR_Strdup(pstart);
436         /*
437         if(endp==pstart || (*endp != '\0')) {
438             errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
439             goto loser;
440         }
441         */
442     } else {
443         _this->verString = NULL;
444         _this->numDigits = 0;
445     }
446 
447     /*
448     // Get the architecture
449     */
450     start = end + 1;
451     if (strchr(start, PLATFORM_SEPARATOR_CHAR)) {
452         errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
453         goto loser;
454     }
455     _this->arch = PR_Strdup(start);
456 
457     if (copy) {
458         PR_Free(copy);
459     }
460     return NULL;
461 loser:
462     if (_this->OS) {
463         PR_Free(_this->OS);
464         _this->OS = NULL;
465     }
466     if (_this->verString) {
467         for (i = 0; i < _this->numDigits; i++) {
468             PR_Free(_this->verString[i]);
469         }
470         PR_Free(_this->verString);
471         _this->verString = NULL;
472     }
473     _this->numDigits = 0;
474     if (_this->arch) {
475         PR_Free(_this->arch);
476         _this->arch = NULL;
477     }
478     if (copy) {
479         PR_Free(copy);
480     }
481 
482     return errStr;
483 }
484 
485 /*
486 //////////////////////////////////////////////////////////////////////////
487 // Method:  operator ==
488 // Class:   Pk11Install_PlatformName
489 // Returns: PR_TRUE if the platform have the same OS, arch, and version
490 */
491 PRBool
Pk11Install_PlatformName_equal(Pk11Install_PlatformName * _this,Pk11Install_PlatformName * cmp)492 Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
493                                Pk11Install_PlatformName* cmp)
494 {
495     int i;
496 
497     if (!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
498         return PR_FALSE;
499     }
500 
501     if (PORT_Strcasecmp(_this->OS, cmp->OS) ||
502         PORT_Strcasecmp(_this->arch, cmp->arch) ||
503         _this->numDigits != cmp->numDigits) {
504         return PR_FALSE;
505     }
506 
507     for (i = 0; i < _this->numDigits; i++) {
508         if (PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
509             return PR_FALSE;
510         }
511     }
512     return PR_TRUE;
513 }
514 
515 /*
516 //////////////////////////////////////////////////////////////////////////
517 // Method:  operator <=
518 // Class:   Pk11Install_PlatformName
519 // Returns: PR_TRUE if the platform have the same OS and arch and a lower
520 //          or equal release.
521 */
522 PRBool
Pk11Install_PlatformName_lteq(Pk11Install_PlatformName * _this,Pk11Install_PlatformName * cmp)523 Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
524                               Pk11Install_PlatformName* cmp)
525 {
526     return (Pk11Install_PlatformName_equal(_this, cmp) ||
527             Pk11Install_PlatformName_lt(_this, cmp))
528                ? PR_TRUE
529                : PR_FALSE;
530 }
531 
532 /*
533 //////////////////////////////////////////////////////////////////////////
534 // Method:  operator <
535 // Class:   Pk11Install_PlatformName
536 // Returns: PR_TRUE if the platform have the same OS and arch and a greater
537 //          release.
538 */
539 PRBool
Pk11Install_PlatformName_lt(Pk11Install_PlatformName * _this,Pk11Install_PlatformName * cmp)540 Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
541                             Pk11Install_PlatformName* cmp)
542 {
543     int i, scmp;
544 
545     if (!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
546         return PR_FALSE;
547     }
548 
549     if (PORT_Strcasecmp(_this->OS, cmp->OS)) {
550         return PR_FALSE;
551     }
552     if (PORT_Strcasecmp(_this->arch, cmp->arch)) {
553         return PR_FALSE;
554     }
555 
556     for (i = 0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
557         scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
558         if (scmp > 0) {
559             return PR_FALSE;
560         } else if (scmp < 0) {
561             return PR_TRUE;
562         }
563     }
564     /* All the digits they have in common are the same. */
565     if (_this->numDigits < cmp->numDigits) {
566         return PR_TRUE;
567     }
568 
569     return PR_FALSE;
570 }
571 
572 /*
573 //////////////////////////////////////////////////////////////////////////
574 // Method:  GetString
575 // Class:   Pk11Install_PlatformName
576 // Returns: String composed of OS, release, and architecture separated
577 //          by the separator char.  Memory is allocated by this function
578 //          but is the responsibility of the caller to de-allocate.
579 */
580 char*
Pk11Install_PlatformName_GetString(Pk11Install_PlatformName * _this)581 Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this)
582 {
583     char* ret;
584     char* ver;
585     char* OS_;
586     char* arch_;
587 
588     OS_ = NULL;
589     arch_ = NULL;
590 
591     OS_ = _this->OS ? _this->OS : "";
592     arch_ = _this->arch ? _this->arch : "";
593 
594     ver = Pk11Install_PlatformName_GetVerString(_this);
595     ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
596                       PLATFORM_SEPARATOR_CHAR, arch_);
597 
598     PR_Free(ver);
599 
600     return ret;
601 }
602 
603 /*
604 //////////////////////////////////////////////////////////////////////////
605 // Method:  GetVerString
606 // Class:   Pk11Install_PlatformName
607 // Returns: The version string for this platform, in the form x.x.x with an
608 //          arbitrary number of digits.  Memory allocated by function,
609 //          must be de-allocated by caller.
610 */
611 char*
Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName * _this)612 Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this)
613 {
614     char* tmp;
615     char* ret;
616     int i;
617     char buf[80];
618 
619     tmp = (char*)PR_Malloc(80 * _this->numDigits + 1);
620     tmp[0] = '\0';
621 
622     for (i = 0; i < _this->numDigits - 1; i++) {
623         sprintf(buf, "%s.", _this->verString[i]);
624         strcat(tmp, buf);
625     }
626     if (i < _this->numDigits) {
627         sprintf(buf, "%s", _this->verString[i]);
628         strcat(tmp, buf);
629     }
630 
631     ret = PR_Strdup(tmp);
632     free(tmp);
633 
634     return ret;
635 }
636 
637 /*
638 //////////////////////////////////////////////////////////////////////////
639 // Method:  Print
640 // Class:   Pk11Install_PlatformName
641 */
642 void
Pk11Install_PlatformName_Print(Pk11Install_PlatformName * _this,int pad)643 Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
644 {
645     char* str = NULL;
646     PAD(pad);
647     printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
648     PAD(pad);
649     printf("Digits: ");
650     if (_this->numDigits == 0) {
651         printf("None\n");
652     } else {
653         str = Pk11Install_PlatformName_GetVerString(_this);
654         printf("%s\n", str);
655         PR_Free(str);
656     }
657     PAD(pad);
658     printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
659 }
660 
661 Pk11Install_Platform*
Pk11Install_Platform_new()662 Pk11Install_Platform_new()
663 {
664     Pk11Install_Platform* new_this;
665     new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
666     Pk11Install_Platform_init(new_this);
667     return new_this;
668 }
669 
670 void
Pk11Install_Platform_init(Pk11Install_Platform * _this)671 Pk11Install_Platform_init(Pk11Install_Platform* _this)
672 {
673     Pk11Install_PlatformName_init(&_this->name);
674     Pk11Install_PlatformName_init(&_this->equivName);
675     _this->equiv = NULL;
676     _this->usesEquiv = PR_FALSE;
677     _this->moduleFile = NULL;
678     _this->moduleName = NULL;
679     _this->modFile = -1;
680     _this->mechFlags = 0;
681     _this->cipherFlags = 0;
682     _this->files = NULL;
683     _this->numFiles = 0;
684 }
685 
686 /*
687 //////////////////////////////////////////////////////////////////////////
688 // Method:  ~Pk11Install_Platform
689 // Class:   Pk11Install_Platform
690 */
691 void
Pk11Install_Platform_delete(Pk11Install_Platform * _this)692 Pk11Install_Platform_delete(Pk11Install_Platform* _this)
693 {
694     Pk11Install_Platform_Cleanup(_this);
695 }
696 
697 /*
698 //////////////////////////////////////////////////////////////////////////
699 // Method:  Cleanup
700 // Class:   Pk11Install_Platform
701 */
702 void
Pk11Install_Platform_Cleanup(Pk11Install_Platform * _this)703 Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
704 {
705     int i;
706     if (_this->moduleFile) {
707         PR_Free(_this->moduleFile);
708         _this->moduleFile = NULL;
709     }
710     if (_this->moduleName) {
711         PR_Free(_this->moduleName);
712         _this->moduleName = NULL;
713     }
714     if (_this->files) {
715         for (i = 0; i < _this->numFiles; i++) {
716             Pk11Install_File_delete(&_this->files[i]);
717         }
718         PR_Free(_this->files);
719         _this->files = NULL;
720     }
721     _this->equiv = NULL;
722     _this->usesEquiv = PR_FALSE;
723     _this->modFile = -1;
724     _this->numFiles = 0;
725     _this->mechFlags = _this->cipherFlags = 0;
726 }
727 
728 /*
729 //////////////////////////////////////////////////////////////////////////
730 // Method:  Generate
731 // Class:   Pk11Install_Platform
732 // Notes:   Creates a platform data structure from a syntax tree.
733 // Returns: NULL for success, otherwise an error message.
734 */
735 char*
Pk11Install_Platform_Generate(Pk11Install_Platform * _this,const Pk11Install_Pair * pair)736 Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
737                               const Pk11Install_Pair* pair)
738 {
739     char* errStr;
740     char* endptr;
741     char* tmp;
742     int i;
743     Pk11Install_ListIter* iter;
744     Pk11Install_Value* val;
745     Pk11Install_Value* subval;
746     Pk11Install_Pair* subpair;
747     Pk11Install_ListIter* subiter;
748     PRBool gotModuleFile, gotModuleName, gotMech,
749         gotCipher, gotFiles, gotEquiv;
750 
751     errStr = NULL;
752     iter = subiter = NULL;
753     val = subval = NULL;
754     subpair = NULL;
755     gotModuleFile = gotModuleName = gotMech = gotCipher = gotFiles = gotEquiv = PR_FALSE;
756     Pk11Install_Platform_Cleanup(_this);
757 
758     errStr = Pk11Install_PlatformName_Generate(&_this->name, pair->key);
759     if (errStr) {
760         tmp = PR_smprintf("%s: %s", pair->key, errStr);
761         PR_smprintf_free(errStr);
762         errStr = tmp;
763         goto loser;
764     }
765 
766     iter = Pk11Install_ListIter_new(pair->list);
767     for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
768         if (val->type == PAIR_VALUE) {
769             subpair = val->pair;
770 
771             if (!PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
772                 if (gotModuleFile) {
773                     errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
774                                          Pk11Install_PlatformName_GetString(&_this->name));
775                     goto loser;
776                 }
777                 subiter = Pk11Install_ListIter_new(subpair->list);
778                 subval = subiter->current;
779                 if (!subval || (subval->type != STRING_VALUE)) {
780                     errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
781                                          Pk11Install_PlatformName_GetString(&_this->name));
782                     goto loser;
783                 }
784                 _this->moduleFile = PR_Strdup(subval->string);
785                 Pk11Install_ListIter_delete(&subiter);
786                 gotModuleFile = PR_TRUE;
787             } else if (!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)) {
788                 if (gotModuleName) {
789                     errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
790                                          Pk11Install_PlatformName_GetString(&_this->name));
791                     goto loser;
792                 }
793                 subiter = Pk11Install_ListIter_new(subpair->list);
794                 subval = subiter->current;
795                 if (!subval || (subval->type != STRING_VALUE)) {
796                     errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
797                                          Pk11Install_PlatformName_GetString(&_this->name));
798                     goto loser;
799                 }
800                 _this->moduleName = PR_Strdup(subval->string);
801                 Pk11Install_ListIter_delete(&subiter);
802                 gotModuleName = PR_TRUE;
803             } else if (!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
804                 endptr = NULL;
805 
806                 if (gotMech) {
807                     errStr = PR_smprintf(errString[REPEAT_MECH],
808                                          Pk11Install_PlatformName_GetString(&_this->name));
809                     goto loser;
810                 }
811                 subiter = Pk11Install_ListIter_new(subpair->list);
812                 subval = subiter->current;
813                 if (!subval || (subval->type != STRING_VALUE)) {
814                     errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
815                                          Pk11Install_PlatformName_GetString(&_this->name));
816                     goto loser;
817                 }
818                 _this->mechFlags = strtol(subval->string, &endptr, 0);
819                 if (*endptr != '\0' || (endptr == subval->string)) {
820                     errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
821                                          Pk11Install_PlatformName_GetString(&_this->name));
822                     goto loser;
823                 }
824                 Pk11Install_ListIter_delete(&subiter);
825                 gotMech = PR_TRUE;
826             } else if (!PORT_Strcasecmp(subpair->key, CIPHER_FLAGS_STRING)) {
827                 endptr = NULL;
828 
829                 if (gotCipher) {
830                     errStr = PR_smprintf(errString[REPEAT_CIPHER],
831                                          Pk11Install_PlatformName_GetString(&_this->name));
832                     goto loser;
833                 }
834                 subiter = Pk11Install_ListIter_new(subpair->list);
835                 subval = subiter->current;
836                 if (!subval || (subval->type != STRING_VALUE)) {
837                     errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
838                                          Pk11Install_PlatformName_GetString(&_this->name));
839                     goto loser;
840                 }
841                 _this->cipherFlags = strtol(subval->string, &endptr, 0);
842                 if (*endptr != '\0' || (endptr == subval->string)) {
843                     errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
844                                          Pk11Install_PlatformName_GetString(&_this->name));
845                     goto loser;
846                 }
847                 Pk11Install_ListIter_delete(&subiter);
848                 gotCipher = PR_TRUE;
849             } else if (!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
850                 if (gotFiles) {
851                     errStr = PR_smprintf(errString[REPEAT_FILES],
852                                          Pk11Install_PlatformName_GetString(&_this->name));
853                     goto loser;
854                 }
855                 subiter = Pk11Install_ListIter_new(subpair->list);
856                 _this->numFiles = subpair->list->numPairs;
857                 _this->files = (Pk11Install_File*)
858                     PR_Malloc(sizeof(Pk11Install_File) * _this->numFiles);
859                 for (i = 0; i < _this->numFiles; i++,
860                     Pk11Install_ListIter_nextItem(subiter)) {
861                     Pk11Install_File_init(&_this->files[i]);
862                     val = subiter->current;
863                     if (val && (val->type == PAIR_VALUE)) {
864                         errStr = Pk11Install_File_Generate(&_this->files[i], val->pair);
865                         if (errStr) {
866                             tmp = PR_smprintf("%s: %s",
867                                               Pk11Install_PlatformName_GetString(&_this->name), errStr);
868                             PR_smprintf_free(errStr);
869                             errStr = tmp;
870                             goto loser;
871                         }
872                     }
873                 }
874                 gotFiles = PR_TRUE;
875             } else if (!PORT_Strcasecmp(subpair->key,
876                                         EQUIVALENT_PLATFORM_STRING)) {
877                 if (gotEquiv) {
878                     errStr = PR_smprintf(errString[REPEAT_EQUIV],
879                                          Pk11Install_PlatformName_GetString(&_this->name));
880                     goto loser;
881                 }
882                 subiter = Pk11Install_ListIter_new(subpair->list);
883                 subval = subiter->current;
884                 if (!subval || (subval->type != STRING_VALUE)) {
885                     errStr = PR_smprintf(errString[BOGUS_EQUIV],
886                                          Pk11Install_PlatformName_GetString(&_this->name));
887                     goto loser;
888                 }
889                 errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
890                                                            subval->string);
891                 if (errStr) {
892                     tmp = PR_smprintf("%s: %s",
893                                       Pk11Install_PlatformName_GetString(&_this->name), errStr);
894                     tmp = PR_smprintf("%s: %s",
895                                       Pk11Install_PlatformName_GetString(&_this->name), errStr);
896                     PR_smprintf_free(errStr);
897                     errStr = tmp;
898                     goto loser;
899                 }
900                 _this->usesEquiv = PR_TRUE;
901             }
902         }
903     }
904 
905     /* Make sure we either have an EquivalentPlatform or all the other info */
906     if (_this->usesEquiv &&
907         (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
908         errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO],
909                              Pk11Install_PlatformName_GetString(&_this->name));
910         goto loser;
911     }
912     if (!gotFiles && !_this->usesEquiv) {
913         errStr = PR_smprintf(errString[NO_FILES],
914                              Pk11Install_PlatformName_GetString(&_this->name));
915         goto loser;
916     }
917     if (!gotModuleFile && !_this->usesEquiv) {
918         errStr = PR_smprintf(errString[NO_MODULE_FILE],
919                              Pk11Install_PlatformName_GetString(&_this->name));
920         goto loser;
921     }
922     if (!gotModuleName && !_this->usesEquiv) {
923         errStr = PR_smprintf(errString[NO_MODULE_NAME],
924                              Pk11Install_PlatformName_GetString(&_this->name));
925         goto loser;
926     }
927 
928     /* Point the modFile pointer to the correct file */
929     if (gotModuleFile) {
930         for (i = 0; i < _this->numFiles; i++) {
931             if (!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath)) {
932                 _this->modFile = i;
933                 break;
934             }
935         }
936         if (_this->modFile == -1) {
937             errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE],
938                                  _this->moduleFile,
939                                  Pk11Install_PlatformName_GetString(&_this->name));
940             goto loser;
941         }
942     }
943 
944 loser:
945     if (iter) {
946         PR_Free(iter);
947     }
948     if (subiter) {
949         PR_Free(subiter);
950     }
951     return errStr;
952 }
953 
954 /*
955 //////////////////////////////////////////////////////////////////////////
956 // Method:      Print
957 // Class:       Pk11Install_Platform
958 */
959 void
Pk11Install_Platform_Print(Pk11Install_Platform * _this,int pad)960 Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
961 {
962     int i;
963 
964     PAD(pad);
965     printf("Name:\n");
966     Pk11Install_PlatformName_Print(&_this->name, pad + PADINC);
967     PAD(pad);
968     printf("equivName:\n");
969     Pk11Install_PlatformName_Print(&_this->equivName, pad + PADINC);
970     PAD(pad);
971     if (_this->usesEquiv) {
972         printf("Uses equiv, which points to:\n");
973         Pk11Install_Platform_Print(_this->equiv, pad + PADINC);
974     } else {
975         printf("Doesn't use equiv\n");
976     }
977     PAD(pad);
978     printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile : "<NULL>");
979     PAD(pad);
980     printf("mechFlags: %lx\n", _this->mechFlags);
981     PAD(pad);
982     printf("cipherFlags: %lx\n", _this->cipherFlags);
983     PAD(pad);
984     printf("Files:\n");
985     for (i = 0; i < _this->numFiles; i++) {
986         Pk11Install_File_Print(&_this->files[i], pad + PADINC);
987         PAD(pad);
988         printf("--------------------\n");
989     }
990 }
991 
992 /*
993 //////////////////////////////////////////////////////////////////////////
994 // Method:      Pk11Install_Info
995 // Class:       Pk11Install_Info
996 */
997 Pk11Install_Info*
Pk11Install_Info_new()998 Pk11Install_Info_new()
999 {
1000     Pk11Install_Info* new_this;
1001     new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
1002     Pk11Install_Info_init(new_this);
1003     return new_this;
1004 }
1005 
1006 void
Pk11Install_Info_init(Pk11Install_Info * _this)1007 Pk11Install_Info_init(Pk11Install_Info* _this)
1008 {
1009     _this->platforms = NULL;
1010     _this->numPlatforms = 0;
1011     _this->forwardCompatible = NULL;
1012     _this->numForwardCompatible = 0;
1013 }
1014 
1015 /*
1016 //////////////////////////////////////////////////////////////////////////
1017 // Method:      ~Pk11Install_Info
1018 // Class:       Pk11Install_Info
1019 */
1020 void
Pk11Install_Info_delete(Pk11Install_Info * _this)1021 Pk11Install_Info_delete(Pk11Install_Info* _this)
1022 {
1023     Pk11Install_Info_Cleanup(_this);
1024 }
1025 
1026 /*
1027 //////////////////////////////////////////////////////////////////////////
1028 // Method:      Cleanup
1029 // Class:       Pk11Install_Info
1030 */
1031 void
Pk11Install_Info_Cleanup(Pk11Install_Info * _this)1032 Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
1033 {
1034     int i;
1035     if (_this->platforms) {
1036         for (i = 0; i < _this->numPlatforms; i++) {
1037             Pk11Install_Platform_delete(&_this->platforms[i]);
1038         }
1039         PR_Free(&_this->platforms);
1040         _this->platforms = NULL;
1041         _this->numPlatforms = 0;
1042     }
1043 
1044     if (_this->forwardCompatible) {
1045         for (i = 0; i < _this->numForwardCompatible; i++) {
1046             Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
1047         }
1048         PR_Free(&_this->forwardCompatible);
1049         _this->numForwardCompatible = 0;
1050     }
1051 }
1052 
1053 /*
1054 //////////////////////////////////////////////////////////////////////////
1055 // Method:      Generate
1056 // Class:       Pk11Install_Info
1057 // Takes:       Pk11Install_ValueList *list, the top-level list
1058 //              resulting from parsing an installer file.
1059 // Returns:     char*, NULL if successful, otherwise an error string.
1060 //              Caller is responsible for freeing memory.
1061 */
1062 char*
Pk11Install_Info_Generate(Pk11Install_Info * _this,const Pk11Install_ValueList * list)1063 Pk11Install_Info_Generate(Pk11Install_Info* _this,
1064                           const Pk11Install_ValueList* list)
1065 {
1066     char* errStr;
1067     Pk11Install_ListIter* iter;
1068     Pk11Install_Value* val;
1069     Pk11Install_Pair* pair;
1070     Pk11Install_ListIter* subiter;
1071     Pk11Install_Value* subval;
1072     Pk11Install_Platform *first, *second;
1073     int i, j;
1074 
1075     errStr = NULL;
1076     iter = subiter = NULL;
1077     Pk11Install_Info_Cleanup(_this);
1078 
1079     iter = Pk11Install_ListIter_new(list);
1080     for (; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
1081         if (val->type == PAIR_VALUE) {
1082             pair = val->pair;
1083 
1084             if (!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
1085                 subiter = Pk11Install_ListIter_new(pair->list);
1086                 _this->numForwardCompatible = pair->list->numStrings;
1087                 _this->forwardCompatible = (Pk11Install_PlatformName*)
1088                     PR_Malloc(sizeof(Pk11Install_PlatformName) *
1089                               _this->numForwardCompatible);
1090                 for (i = 0; i < _this->numForwardCompatible; i++,
1091                     Pk11Install_ListIter_nextItem(subiter)) {
1092                     subval = subiter->current;
1093                     if (subval->type == STRING_VALUE) {
1094                         errStr = Pk11Install_PlatformName_Generate(
1095                             &_this->forwardCompatible[i], subval->string);
1096                         if (errStr) {
1097                             goto loser;
1098                         }
1099                     }
1100                 }
1101                 Pk11Install_ListIter_delete(&subiter);
1102             } else if (!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
1103                 subiter = Pk11Install_ListIter_new(pair->list);
1104                 _this->numPlatforms = pair->list->numPairs;
1105                 _this->platforms = (Pk11Install_Platform*)
1106                     PR_Malloc(sizeof(Pk11Install_Platform) *
1107                               _this->numPlatforms);
1108                 for (i = 0; i < _this->numPlatforms; i++,
1109                     Pk11Install_ListIter_nextItem(subiter)) {
1110                     Pk11Install_Platform_init(&_this->platforms[i]);
1111                     subval = subiter->current;
1112                     if (subval->type == PAIR_VALUE) {
1113                         errStr = Pk11Install_Platform_Generate(&_this->platforms[i], subval->pair);
1114                         if (errStr) {
1115                             goto loser;
1116                         }
1117                     }
1118                 }
1119                 Pk11Install_ListIter_delete(&subiter);
1120             }
1121         }
1122     }
1123 
1124     if (_this->numPlatforms == 0) {
1125         errStr = PR_smprintf(errString[NO_PLATFORMS]);
1126         goto loser;
1127     }
1128 
1129     /*
1130     //
1131     // Now process equivalent platforms
1132     //
1133 
1134     // First the naive pass
1135     */
1136     for (i = 0; i < _this->numPlatforms; i++) {
1137         if (_this->platforms[i].usesEquiv) {
1138             _this->platforms[i].equiv = NULL;
1139             for (j = 0; j < _this->numPlatforms; j++) {
1140                 if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
1141                                                    &_this->platforms[j].name)) {
1142                     if (i == j) {
1143                         errStr = PR_smprintf(errString[EQUIV_LOOP],
1144                                              Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
1145                         goto loser;
1146                     }
1147                     _this->platforms[i].equiv = &_this->platforms[j];
1148                     break;
1149                 }
1150             }
1151             if (_this->platforms[i].equiv == NULL) {
1152                 errStr = PR_smprintf(errString[BOGUS_EQUIV],
1153                                      Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
1154                 goto loser;
1155             }
1156         }
1157     }
1158 
1159     /*
1160     // Now the intelligent pass, which will also detect loops.
1161     // We will send two pointers through the linked list of equivalent
1162     // platforms. Both start with the current node.  "first" traverses
1163     // two nodes for each iteration.  "second" lags behind, only traversing
1164     // one node per iteration.  Eventually one of two things will happen:
1165     // first will hit the end of the list (a platform that doesn't use
1166     // an equivalency), or first will equal second if there is a loop.
1167     */
1168     for (i = 0; i < _this->numPlatforms; i++) {
1169         if (_this->platforms[i].usesEquiv) {
1170             second = _this->platforms[i].equiv;
1171             if (!second->usesEquiv) {
1172                 /* The first link is the terminal node */
1173                 continue;
1174             }
1175             first = second->equiv;
1176             while (first->usesEquiv) {
1177                 if (first == second) {
1178                     errStr = PR_smprintf(errString[EQUIV_LOOP],
1179                                          Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
1180                     goto loser;
1181                 }
1182                 first = first->equiv;
1183                 if (!first->usesEquiv) {
1184                     break;
1185                 }
1186                 if (first == second) {
1187                     errStr = PR_smprintf(errString[EQUIV_LOOP],
1188                                          Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
1189                     goto loser;
1190                 }
1191                 second = second->equiv;
1192                 first = first->equiv;
1193             }
1194             _this->platforms[i].equiv = first;
1195         }
1196     }
1197 
1198 loser:
1199     if (iter) {
1200         Pk11Install_ListIter_delete(&iter);
1201     }
1202     if (subiter) {
1203         Pk11Install_ListIter_delete(&subiter);
1204     }
1205     return errStr;
1206 }
1207 
1208 /*
1209 //////////////////////////////////////////////////////////////////////////
1210 // Method:      GetBestPlatform
1211 // Class:       Pk11Install_Info
1212 // Takes:       char *myPlatform, the platform we are currently running
1213 //              on.
1214 */
1215 Pk11Install_Platform*
Pk11Install_Info_GetBestPlatform(Pk11Install_Info * _this,char * myPlatform)1216 Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char* myPlatform)
1217 {
1218     Pk11Install_PlatformName plat;
1219     char* errStr;
1220     int i, j;
1221 
1222     errStr = NULL;
1223 
1224     Pk11Install_PlatformName_init(&plat);
1225     if ((errStr = Pk11Install_PlatformName_Generate(&plat, myPlatform))) {
1226         PR_smprintf_free(errStr);
1227         return NULL;
1228     }
1229 
1230     /* First try real platforms */
1231     for (i = 0; i < _this->numPlatforms; i++) {
1232         if (Pk11Install_PlatformName_equal(&_this->platforms[i].name, &plat)) {
1233             if (_this->platforms[i].equiv) {
1234                 return _this->platforms[i].equiv;
1235             } else {
1236                 return &_this->platforms[i];
1237             }
1238         }
1239     }
1240 
1241     /* Now try forward compatible platforms */
1242     for (i = 0; i < _this->numForwardCompatible; i++) {
1243         if (Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i], &plat)) {
1244             break;
1245         }
1246     }
1247     if (i == _this->numForwardCompatible) {
1248         return NULL;
1249     }
1250 
1251     /* Got a forward compatible name, find the actual platform. */
1252     for (j = 0; j < _this->numPlatforms; j++) {
1253         if (Pk11Install_PlatformName_equal(&_this->platforms[j].name,
1254                                            &_this->forwardCompatible[i])) {
1255             if (_this->platforms[j].equiv) {
1256                 return _this->platforms[j].equiv;
1257             } else {
1258                 return &_this->platforms[j];
1259             }
1260         }
1261     }
1262 
1263     return NULL;
1264 }
1265 
1266 /*
1267 //////////////////////////////////////////////////////////////////////////
1268 // Method:      Print
1269 // Class:       Pk11Install_Info
1270 */
1271 void
Pk11Install_Info_Print(Pk11Install_Info * _this,int pad)1272 Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
1273 {
1274     int i;
1275 
1276     PAD(pad);
1277     printf("Forward Compatible:\n");
1278     for (i = 0; i < _this->numForwardCompatible; i++) {
1279         Pk11Install_PlatformName_Print(&_this->forwardCompatible[i], pad + PADINC);
1280         PAD(pad);
1281         printf("-------------------\n");
1282     }
1283     PAD(pad);
1284     printf("Platforms:\n");
1285     for (i = 0; i < _this->numPlatforms; i++) {
1286         Pk11Install_Platform_Print(&_this->platforms[i], pad + PADINC);
1287         PAD(pad);
1288         printf("-------------------\n");
1289     }
1290 }
1291 
1292 /*
1293 //////////////////////////////////////////////////////////////////////////
1294 */
1295 static char*
PR_Strdup(const char * str)1296 PR_Strdup(const char* str)
1297 {
1298     char* tmp;
1299     tmp = (char*)PR_Malloc((unsigned int)(strlen(str) + 1));
1300     strcpy(tmp, str);
1301     return tmp;
1302 }
1303 
1304 /* The global value list, the top of the tree */
1305 Pk11Install_ValueList* Pk11Install_valueList = NULL;
1306 
1307 /****************************************************************************/
1308 void
Pk11Install_ValueList_AddItem(Pk11Install_ValueList * _this,Pk11Install_Value * item)1309 Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
1310                               Pk11Install_Value* item)
1311 {
1312     _this->numItems++;
1313     if (item->type == STRING_VALUE) {
1314         _this->numStrings++;
1315     } else {
1316         _this->numPairs++;
1317     }
1318     item->next = _this->head;
1319     _this->head = item;
1320 }
1321 
1322 /****************************************************************************/
1323 Pk11Install_ListIter*
Pk11Install_ListIter_new_default()1324 Pk11Install_ListIter_new_default()
1325 {
1326     Pk11Install_ListIter* new_this;
1327     new_this = (Pk11Install_ListIter*)
1328         PR_Malloc(sizeof(Pk11Install_ListIter));
1329     Pk11Install_ListIter_init(new_this);
1330     return new_this;
1331 }
1332 
1333 /****************************************************************************/
1334 void
Pk11Install_ListIter_init(Pk11Install_ListIter * _this)1335 Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
1336 {
1337     _this->list = NULL;
1338     _this->current = NULL;
1339 }
1340 
1341 /****************************************************************************/
1342 Pk11Install_ListIter*
Pk11Install_ListIter_new(const Pk11Install_ValueList * _list)1343 Pk11Install_ListIter_new(const Pk11Install_ValueList* _list)
1344 {
1345     Pk11Install_ListIter* new_this;
1346     new_this = (Pk11Install_ListIter*)
1347         PR_Malloc(sizeof(Pk11Install_ListIter));
1348     new_this->list = _list;
1349     new_this->current = _list->head;
1350     return new_this;
1351 }
1352 
1353 /****************************************************************************/
1354 void
Pk11Install_ListIter_delete(Pk11Install_ListIter ** _this)1355 Pk11Install_ListIter_delete(Pk11Install_ListIter** _this)
1356 {
1357     (*_this)->list = NULL;
1358     (*_this)->current = NULL;
1359     PR_Free(*_this);
1360     *_this = NULL;
1361 }
1362 
1363 /****************************************************************************/
1364 void
Pk11Install_ListIter_reset(Pk11Install_ListIter * _this)1365 Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
1366 {
1367     if (_this->list) {
1368         _this->current = _this->list->head;
1369     }
1370 }
1371 
1372 /*************************************************************************/
1373 Pk11Install_Value*
Pk11Install_ListIter_nextItem(Pk11Install_ListIter * _this)1374 Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
1375 {
1376     if (_this->current) {
1377         _this->current = _this->current->next;
1378     }
1379 
1380     return _this->current;
1381 }
1382 
1383 /****************************************************************************/
1384 Pk11Install_ValueList*
Pk11Install_ValueList_new()1385 Pk11Install_ValueList_new()
1386 {
1387     Pk11Install_ValueList* new_this;
1388     new_this = (Pk11Install_ValueList*)
1389         PR_Malloc(sizeof(Pk11Install_ValueList));
1390     new_this->numItems = 0;
1391     new_this->numPairs = 0;
1392     new_this->numStrings = 0;
1393     new_this->head = NULL;
1394     return new_this;
1395 }
1396 
1397 /****************************************************************************/
1398 void
Pk11Install_ValueList_delete(Pk11Install_ValueList * _this)1399 Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
1400 {
1401 
1402     Pk11Install_Value* tmp;
1403     Pk11Install_Value* list;
1404     list = _this->head;
1405 
1406     while (list != NULL) {
1407         tmp = list;
1408         list = list->next;
1409         PR_Free(tmp);
1410     }
1411     PR_Free(_this);
1412 }
1413 
1414 /****************************************************************************/
1415 Pk11Install_Value*
Pk11Install_Value_new_default()1416 Pk11Install_Value_new_default()
1417 {
1418     Pk11Install_Value* new_this;
1419     new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
1420     new_this->type = STRING_VALUE;
1421     new_this->string = NULL;
1422     new_this->pair = NULL;
1423     new_this->next = NULL;
1424     return new_this;
1425 }
1426 
1427 /****************************************************************************/
1428 Pk11Install_Value*
Pk11Install_Value_new(ValueType _type,Pk11Install_Pointer ptr)1429 Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
1430 {
1431     Pk11Install_Value* new_this;
1432     new_this = Pk11Install_Value_new_default();
1433     new_this->type = _type;
1434     if (_type == STRING_VALUE) {
1435         new_this->pair = NULL;
1436         new_this->string = ptr.string;
1437     } else {
1438         new_this->string = NULL;
1439         new_this->pair = ptr.pair;
1440     }
1441     return new_this;
1442 }
1443 
1444 /****************************************************************************/
1445 void
Pk11Install_Value_delete(Pk11Install_Value * _this)1446 Pk11Install_Value_delete(Pk11Install_Value* _this)
1447 {
1448     if (_this->type == STRING_VALUE) {
1449         PR_Free(_this->string);
1450     } else {
1451         PR_Free(_this->pair);
1452     }
1453 }
1454 
1455 /****************************************************************************/
1456 Pk11Install_Pair*
Pk11Install_Pair_new_default()1457 Pk11Install_Pair_new_default()
1458 {
1459     return Pk11Install_Pair_new(NULL, NULL);
1460 }
1461 
1462 /****************************************************************************/
1463 Pk11Install_Pair*
Pk11Install_Pair_new(char * _key,Pk11Install_ValueList * _list)1464 Pk11Install_Pair_new(char* _key, Pk11Install_ValueList* _list)
1465 {
1466     Pk11Install_Pair* new_this;
1467     new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
1468     new_this->key = _key;
1469     new_this->list = _list;
1470     return new_this;
1471 }
1472 
1473 /****************************************************************************/
1474 void
Pk11Install_Pair_delete(Pk11Install_Pair * _this)1475 Pk11Install_Pair_delete(Pk11Install_Pair* _this)
1476 {
1477     PR_Free(_this->key);
1478     Pk11Install_ValueList_delete(_this->list);
1479 }
1480 
1481 /*************************************************************************/
1482 void
Pk11Install_Pair_Print(Pk11Install_Pair * _this,int pad)1483 Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
1484 {
1485     while (_this) {
1486         /*PAD(pad); printf("**Pair\n");
1487         PAD(pad); printf("***Key====\n");*/
1488         PAD(pad);
1489         printf("%s {\n", _this->key);
1490         /*PAD(pad); printf("====\n");*/
1491         /*PAD(pad); printf("***ValueList\n");*/
1492         Pk11Install_ValueList_Print(_this->list, pad + PADINC);
1493         PAD(pad);
1494         printf("}\n");
1495     }
1496 }
1497 
1498 /*************************************************************************/
1499 void
Pk11Install_ValueList_Print(Pk11Install_ValueList * _this,int pad)1500 Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
1501 {
1502     Pk11Install_Value* v;
1503 
1504     /*PAD(pad);printf("**Value List**\n");*/
1505     for (v = _this->head; v != NULL; v = v->next) {
1506         Pk11Install_Value_Print(v, pad);
1507     }
1508 }
1509 
1510 /*************************************************************************/
1511 void
Pk11Install_Value_Print(Pk11Install_Value * _this,int pad)1512 Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
1513 {
1514     /*PAD(pad); printf("**Value, type=%s\n",
1515         type==STRING_VALUE ? "string" : "pair");*/
1516     if (_this->type == STRING_VALUE) {
1517         /*PAD(pad+PADINC); printf("====\n");*/
1518         PAD(pad);
1519         printf("%s\n", _this->string);
1520         /*PAD(pad+PADINC); printf("====\n");*/
1521     } else {
1522         Pk11Install_Pair_Print(_this->pair, pad + PADINC);
1523     }
1524 }
1525