LCOV - code coverage report
Current view: top level - Core - OOPListParsing.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 12 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOPListParsing.m
       4             : 
       5             : Oolite
       6             : Copyright (C) 2004-2013 Giles C Williams and contributors
       7             : 
       8             : This program is free software; you can redistribute it and/or
       9             : modify it under the terms of the GNU General Public License
      10             : as published by the Free Software Foundation; either version 2
      11             : of the License, or (at your option) any later version.
      12             : 
      13             : This program is distributed in the hope that it will be useful,
      14             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             : GNU General Public License for more details.
      17             : 
      18             : You should have received a copy of the GNU General Public License
      19             : along with this program; if not, write to the Free Software
      20             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      21             : MA 02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : 
      26             : #import "OOPListParsing.h"
      27             : #import "OOLogging.h"
      28             : #import "OOStringParsing.h"
      29             : #import "NSDataOOExtensions.h"
      30             : #include <ctype.h>
      31             : #include <string.h>
      32             : 
      33             : 
      34             : #if !OOLITE_GNUSTEP
      35           0 : #define NO_DYNAMIC_PLIST_DTD_CHANGE
      36             : #endif
      37             : 
      38             : 
      39           0 : static NSString * const kOOLogPListFoundationParseError         = @"plist.parse.failed";
      40           0 : static NSString * const kOOLogPListWrongType                            = @"plist.wrongType";
      41             : 
      42             : 
      43             : #ifndef NO_DYNAMIC_PLIST_DTD_CHANGE
      44             : static NSData *ChangeDTDIfApplicable(NSData *data);
      45             : #endif
      46             : 
      47             : static NSData *CopyDataFromFile(NSString *path);
      48             : static id ValueIfClass(id value, Class class);
      49             : 
      50             : 
      51           0 : id OOPropertyListFromData(NSData *data, NSString *whereFrom)
      52             : {
      53             :         id                      result = nil;
      54             :         NSString        *error = nil;
      55             :         
      56             :         if (data != nil)
      57             :         {
      58             : #ifndef NO_DYNAMIC_PLIST_DTD_CHANGE
      59             :                 data = ChangeDTDIfApplicable(data);
      60             : #endif
      61             :                 
      62             :                 result = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:&error];
      63             :                 if (result == nil)      // Foundation parser failed
      64             :                 {       
      65             : #if OOLITE_RELEASE_PLIST_ERROR_STRINGS
      66             :                         [error autorelease];
      67             : #endif
      68             :                         // Ensure we can say something sensible...
      69             :                         if (error == nil) error = @"<no error message>";
      70             :                         if (whereFrom == nil) whereFrom = @"<data in memory>";
      71             :                         
      72             :                         OOLog(kOOLogPListFoundationParseError, @"Failed to parse %@ as a property list.\n%@", whereFrom, error);
      73             :                 }
      74             :         }
      75             :         
      76             :         return result;
      77             : }
      78             : 
      79             : 
      80           0 : id OOPropertyListFromFile(NSString *path)
      81             : {
      82             :         id                      result = nil;
      83             :         NSData          *data = nil;
      84             :         
      85             :         if (path != nil)
      86             :         {
      87             :                 // Load file, if it exists...
      88             :                 data = CopyDataFromFile(path);
      89             :                 if (data != nil)
      90             :                 {
      91             :                         // ...and parse it
      92             :                         result = OOPropertyListFromData(data, path);
      93             :                         [data release];
      94             :                 }
      95             :                 // Non-existent file is not an error.
      96             :         }
      97             :         
      98             :         return result;
      99             : }
     100             : 
     101             : 
     102             : #ifndef NO_DYNAMIC_PLIST_DTD_CHANGE
     103             : static NSData *ChangeDTDIfApplicable(NSData *data)
     104             : {
     105             :         const uint8_t           *bytes = NULL;
     106             :         uint8_t                         *newBytes = NULL;
     107             :         size_t                          length,
     108             :                                                 newLength,
     109             :                                                 offset = 0,
     110             :                                                 newOffset = 0;
     111             :         const char                      xmlDeclLine[] = "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>";
     112             :         const char                      *appleDTDLines[] = 
     113             :                                                 {
     114             :                                                         "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">",
     115             :                                                         "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">",
     116             :                                                         NULL
     117             :                                                 };
     118             :         const char                      gstepDTDLine[] = "<!DOCTYPE plist PUBLIC \"-//GNUstep//DTD plist 0.9//EN\" \"http://www.gnustep.org/plist-0_9.xml\">";
     119             :         const char                      *srcDTDLine = NULL;
     120             :         size_t                          srcDTDLineSize = 0;
     121             :         unsigned                        i;
     122             :         
     123             :         length = [data length];
     124             :         if (length < sizeof xmlDeclLine) return data;
     125             :         
     126             :         bytes = [data bytes];
     127             :         
     128             :         // Check if it starts with an XML declaration. Bogus: there are valid XML declarations which don't match xmlDeclLine.
     129             :         if (memcmp(bytes, xmlDeclLine, sizeof xmlDeclLine - 1) != 0) return data;
     130             :         
     131             :         offset += sizeof xmlDeclLine - 1;
     132             :         while (offset < length && isspace(bytes[offset]))  ++offset;
     133             :         
     134             :         // Check if first non-blank stuff after XML declaration is any known Apple plist DTD. Also somewhat bogus.
     135             :         for (i = 0; ; i++)
     136             :         {
     137             :                 srcDTDLine = appleDTDLines[i];
     138             :                 if (srcDTDLine == NULL)  return data;  // No matches
     139             :                 
     140             :                 srcDTDLineSize = strlen(appleDTDLines[i]);
     141             :                 
     142             :                 if (srcDTDLineSize <= length - offset &&
     143             :                         memcmp(bytes + offset, srcDTDLine, srcDTDLineSize) == 0)
     144             :                 {
     145             :                         // Match
     146             :                         break;
     147             :                 }
     148             :         }
     149             :         
     150             :         offset += srcDTDLineSize;
     151             :         
     152             :         newLength = length - offset + sizeof xmlDeclLine + sizeof gstepDTDLine - 1;
     153             :         newBytes = malloc(newLength);
     154             :         if (newBytes == NULL) return data;
     155             :         
     156             :         // Construct modified version with altered DTD line
     157             :         memcpy(newBytes, xmlDeclLine, sizeof xmlDeclLine - 1);
     158             :         newOffset = sizeof xmlDeclLine - 1;
     159             :         newBytes[newOffset++] = '\n';
     160             :         memcpy(newBytes + newOffset, gstepDTDLine, sizeof gstepDTDLine - 1);
     161             :         newOffset += sizeof gstepDTDLine - 1;
     162             :         memcpy(newBytes + newOffset, bytes + offset, length - offset);
     163             :         
     164             :         return [NSData dataWithBytes:newBytes length:newLength];
     165             : }
     166             : #endif
     167             : 
     168             : 
     169             : /*      Load data from file. Returns a retained pointer.
     170             :         -initWithContentsOfMappedFile fails quietly under OS X if there's no file,
     171             :         but GNUstep complains.
     172             : */
     173           0 : static NSData *CopyDataFromFile(NSString *path)
     174             : {
     175             :         return [[NSData oo_dataWithOXZFile:path] retain];
     176             : #if 0
     177             : // without OXZ extension. Code to be deleted once everything is working
     178             : #if OOLITE_MAC_OS_X
     179             :         return [[NSData alloc] initWithContentsOfMappedFile:path];
     180             : #else
     181             :         NSFileManager   *fmgr = [NSFileManager defaultManager];
     182             :         BOOL                    dir;
     183             :         
     184             :         if ([fmgr fileExistsAtPath:path isDirectory:&dir])
     185             :         {
     186             :                 if (!dir)
     187             :                 {
     188             :                         return [[NSData alloc] initWithContentsOfMappedFile:path];
     189             :                 }
     190             :                 else
     191             :                 {
     192             :                         OOLog(kOOLogFileNotFound, @"Expected property list but found directory at %@", path);
     193             :                 }
     194             :         }
     195             :         
     196             :         return nil;
     197             : #endif
     198             : #endif
     199             : }
     200             : // Wrappers which ensure that the plist contains the right type of object.
     201           0 : NSDictionary *OODictionaryFromData(NSData *data, NSString *whereFrom)
     202             : {
     203             :         id result = OOPropertyListFromData(data, whereFrom);
     204             :         return ValueIfClass(result, [NSDictionary class]);
     205             : }
     206             : 
     207             : 
     208           0 : NSDictionary *OODictionaryFromFile(NSString *path)
     209             : {
     210             :         id result = OOPropertyListFromFile(path);
     211             :         return ValueIfClass(result, [NSDictionary class]);
     212             : }
     213             : 
     214             : 
     215           0 : NSArray *OOArrayFromData(NSData *data, NSString *whereFrom)
     216             : {
     217             :         id result = OOPropertyListFromData(data, whereFrom);
     218             :         return ValueIfClass(result, [NSArray class]);
     219             : }
     220             : 
     221             : 
     222           0 : NSArray *OOArrayFromFile(NSString *path)
     223             : {
     224             :         id result = OOPropertyListFromFile(path);
     225             :         return ValueIfClass(result, [NSArray class]);
     226             : }
     227             : 
     228             : 
     229             : // Ensure that object is of desired class.
     230           0 : static id ValueIfClass(id value, Class class)
     231             : {
     232             :         if (value != nil && ![value isKindOfClass:class])
     233             :         {
     234             :                 OOLog(kOOLogPListWrongType, @"Property list is wrong type - expected %@, got %@.", class, [value class]);
     235             :                 value = nil;
     236             :         }
     237             :         return value;
     238             : }

Generated by: LCOV version 1.14