]> granicus.if.org Git - imagemagick/commitdiff
https://github.com/ImageMagick/ImageMagick/issues/848
authorCristy <urban-warrior@imagemagick.org>
Sun, 29 Oct 2017 14:37:57 +0000 (10:37 -0400)
committerCristy <urban-warrior@imagemagick.org>
Sun, 29 Oct 2017 14:37:57 +0000 (10:37 -0400)
coders/json.c

index 9449022a388c2f85f19cd8de685785576c291bc0..04a39ff536e58f3affa18a4d4eb932dd312c5c6f 100644 (file)
@@ -78,7 +78,7 @@
 /*
   Typedef declarations.
 */
-typedef struct _IptcValue
+typedef struct _IPTCInfo
 {
   long
     dataset,
@@ -90,7 +90,7 @@ typedef struct _IptcValue
   char
     tag[32],
     ***values;
-} IptcValue;
+} IPTCInfo;
 \f
 /*
   Forward declarations.
@@ -186,7 +186,8 @@ ModuleExport void UnregisterJSONImage(void)
 %
 */
 
-static void JsonFormatLocaleFile(FILE *file,const char *format,const char *value)
+static void JSONFormatLocaleFile(FILE *file,const char *format,
+  const char *value)
 {
   char
     *escaped_json;
@@ -201,81 +202,109 @@ static void JsonFormatLocaleFile(FILE *file,const char *format,const char *value
     length;
 
   assert(format != (const char *) NULL);
-  if (value == (char *) NULL || *value == '\0')
-  {
-    (void) FormatLocaleFile(file,format,"null");
-    return;
-  }
+  if ((value == (char *) NULL) || (*value == '\0'))
+    {
+      (void) FormatLocaleFile(file,format,"null");
+      return;
+    }
   length=strlen(value)+2;
   /*
-    Find all the chars that need escaping and increase the dest length counter
+    Find all the chars that need escaping and increase the dest length counter.
   */
   for (p=value; *p != '\0'; p++)
+  {
+    switch (*p)
     {
-      switch (*p)
-        {
-          case '"':
-          case '\b':
-          case '\f':
-          case '\n':
-          case '\r':
-          case '\t':
-          case '\\':
-            if (~length < 1)
-              return;
-            length++;
-            break;
-          default:
-            break;
-        }
+      case '"':
+      case '\b':
+      case '\f':
+      case '\n':
+      case '\r':
+      case '\t':
+      case '\\':
+      {
+        if (~length < 1)
+          return;
+        length++;
+        break;
+      }
+      default:
+      {
+        if (((int) *p >= 0x00) && ((int) *p <= 0x1f))
+          length+=6;
+        break;
+      }
     }
+  }
   escaped_json=(char *) NULL;
   if (~length >= (MagickPathExtent-1))
     escaped_json=(char *) AcquireQuantumMemory(length+MagickPathExtent,
       sizeof(*escaped_json));
   if (escaped_json == (char *) NULL)
-  {
-    (void) FormatLocaleFile(file,format,"null");
-    return;
-  }
+    {
+      (void) FormatLocaleFile(file,format,"null");
+      return;
+    }
   q=escaped_json;
   *q++='"';
   for (p=value; *p != '\0'; p++)
+  {
+    switch (*p)
     {
-      switch (*p)
-        {
-          case '"':
-            *q++='\\';
-            *q++=(*p);
-            break;
-          case '\b':
-            *q++='\\';
-            *q++='b';
-            break;
-          case '\f':
-            *q++='\\';
-            *q++='f';
-            break;
-          case '\n':
-            *q++='\\';
-            *q++='n';
-            break;
-          case '\r':
-            *q++='\\';
-            *q++='r';
-            break;
-          case '\t':
-            *q++='\\';
-            *q++='t';
-            break;
-          case '\\':
-            *q++='\\';
-            *q++='\\';
-            break;
-          default:
-            *q++=(*p);
+      case '"':
+      {
+        *q++='\\';
+        *q++=(*p);
+        break;
+      }
+      case '\b':
+      {
+        *q++='\\';
+        *q++='b';
+        break;
+      }
+      case '\f':
+      {
+        *q++='\\';
+        *q++='f';
+        break;
+      }
+      case '\n':
+      {
+        *q++='\\';
+        *q++='n';
+        break;
+      }
+      case '\r':
+      {
+        *q++='\\';
+        *q++='r';
+        break;
+      }
+      case '\t':
+      {
+        *q++='\\';
+        *q++='t';
+        break;
+      }
+      case '\\':
+      {
+        *q++='\\';
+        *q++='\\';
+        break;
+      }
+      default:
+      {
+        if (((int) *p >= 0x00) && ((int) *p <= 0x1f))
+          {
+            (void) FormatLocaleString(q,7,"\\u%04X",(int) *p);
+            q+=6;
             break;
-        }
+          }
+        *q++=(*p);
+        break;
+      }
+    }
   }
   *q++='"';
   *q='\0';
@@ -710,7 +739,7 @@ static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
   const char
     *tag;
 
-  IptcValue
+  IPTCInfo
     *value,
     **values;
 
@@ -729,7 +758,7 @@ static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
     length,
     profile_length;
 
-  values=(IptcValue **) NULL;
+  values=(IPTCInfo **) NULL;
   count=0;
   profile_length=GetStringInfoLength(profile);
   for (i=0; i < (ssize_t) profile_length; i+=(ssize_t) length)
@@ -740,22 +769,22 @@ static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
       continue;
     dataset=GetStringInfoDatum(profile)[i++];
     record=GetStringInfoDatum(profile)[i++];
-    value=(IptcValue *) NULL;
+    value=(IPTCInfo *) NULL;
     for (j=0; j < (ssize_t) count; j++)
     {
       if ((values[j]->record == record) && (values[j]->dataset == dataset))
         value=values[j];
     }
-    if (value == (IptcValue *) NULL)
+    if (value == (IPTCInfo *) NULL)
       {
-        values=(IptcValue **) ResizeQuantumMemory(values,count+1,
+        values=(IPTCInfo **) ResizeQuantumMemory(values,count+1,
           sizeof(*values));
-        if (values == (IptcValue **) NULL)
+        if (values == (IPTCInfo **) NULL)
           break;
-        value=(IptcValue *) AcquireMagickMemory(sizeof(*value));
-        if (value == (IptcValue *) NULL)
+        value=(IPTCInfo *) AcquireMagickMemory(sizeof(*value));
+        if (value == (IPTCInfo *) NULL)
           break;
-        /* Check the tag length in IptcValue when a new tag is added */
+        /* Check the tag length in IPTCInfo when a new tag is added */
         switch (record)
         {
           case 5: tag="Image Name"; break;
@@ -843,7 +872,7 @@ static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
         attribute=DestroyString(attribute);
       }
   }
-  if (values != (IptcValue **) NULL)
+  if (values != (IPTCInfo **) NULL)
     {
       for (i=0; i < (ssize_t) count; i++)
       {
@@ -861,7 +890,7 @@ static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
               {
                 if (j > 0 || k > 0)
                   (void) FormatLocaleFile(file,",");
-                JsonFormatLocaleFile(file,"%s",value->values[j][k]);
+                JSONFormatLocaleFile(file,"%s",value->values[j][k]);
                 value->values[j][k]=(char *) RelinquishMagickMemory(
                   value->values[j][k]);
               }
@@ -871,9 +900,9 @@ static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
             value->values=(char ***) RelinquishMagickMemory(value->values);
             (void) FormatLocaleFile(file,"],\n");
           }
-        values[i]=(IptcValue *) RelinquishMagickMemory(values[i]);
+        values[i]=(IPTCInfo *) RelinquishMagickMemory(values[i]);
       }
-      values=(IptcValue **) RelinquishMagickMemory(values);
+      values=(IPTCInfo **) RelinquishMagickMemory(values);
     }
 }
 
@@ -952,7 +981,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
   ping=p == (const Quantum *) NULL ? MagickTrue : MagickFalse;
   (void) ping;
   (void) SignatureImage(image,exception);
-  JsonFormatLocaleFile(file,"{\n  \"image\": {\n    \"name\": %s,\n",
+  JSONFormatLocaleFile(file,"{\n  \"image\": {\n    \"name\": %s,\n",
     image->filename);
   if (*image->magick_filename != '\0')
     if (LocaleCompare(image->magick_filename,image->filename) != 0)
@@ -961,19 +990,19 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
           filename[MagickPathExtent];
 
         GetPathComponent(image->magick_filename,TailPath,filename);
-        JsonFormatLocaleFile(file,"    \"baseName\": %s,\n",filename);
+        JSONFormatLocaleFile(file,"    \"baseName\": %s,\n",filename);
       }
-  JsonFormatLocaleFile(file,"    \"format\": %s,\n",image->magick);
+  JSONFormatLocaleFile(file,"    \"format\": %s,\n",image->magick);
   magick_info=GetMagickInfo(image->magick,exception);
   if ((magick_info != (const MagickInfo *) NULL) &&
       (GetMagickDescription(magick_info) != (const char *) NULL))
-    JsonFormatLocaleFile(file,"    \"formatDescription\": %s,\n",
+    JSONFormatLocaleFile(file,"    \"formatDescription\": %s,\n",
       image->magick);
   if ((magick_info != (const MagickInfo *) NULL) &&
       (GetMagickMimeType(magick_info) != (const char *) NULL))
-    JsonFormatLocaleFile(file,"    \"mimeType\": %s,\n",GetMagickMimeType(
+    JSONFormatLocaleFile(file,"    \"mimeType\": %s,\n",GetMagickMimeType(
       magick_info));
-  JsonFormatLocaleFile(file,"    \"class\": %s,\n",CommandOptionToMnemonic(
+  JSONFormatLocaleFile(file,"    \"class\": %s,\n",CommandOptionToMnemonic(
     MagickClassOptions,(ssize_t) image->storage_class));
   (void) FormatLocaleFile(file,"    \"geometry\": {\n"
     "      \"width\": %.20g,\n      \"height\": %.20g,\n"
@@ -996,20 +1025,20 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
         image->columns/image->resolution.x,(double) image->rows/
         image->resolution.y);
     }
-  JsonFormatLocaleFile(file,"    \"units\": %s,\n",CommandOptionToMnemonic(
+  JSONFormatLocaleFile(file,"    \"units\": %s,\n",CommandOptionToMnemonic(
     MagickResolutionOptions,(ssize_t) image->units));
   colorspace=image->colorspace;
   type=IdentifyImageType(image,exception);
   if ((type == BilevelType) || (type == GrayscaleType) ||
       (type == GrayscaleAlphaType))
     colorspace=GRAYColorspace;
-  JsonFormatLocaleFile(file,"    \"type\": %s,\n",CommandOptionToMnemonic(
+  JSONFormatLocaleFile(file,"    \"type\": %s,\n",CommandOptionToMnemonic(
     MagickTypeOptions,(ssize_t) type));
   base_type=GetImageType(image);
   if (type != base_type)
-    JsonFormatLocaleFile(file,"    \"baseType\": %s,\n",
+    JSONFormatLocaleFile(file,"    \"baseType\": %s,\n",
       CommandOptionToMnemonic(MagickTypeOptions,(ssize_t) base_type));
-  JsonFormatLocaleFile(file,"    \"endianess\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"endianess\": %s,\n",
     CommandOptionToMnemonic(MagickEndianOptions,(ssize_t) image->endian));
   locate=GetImageArtifact(image,"identify:locate");
   if (locate == (const char *) NULL)
@@ -1082,7 +1111,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
   /*
     Detail channel depth and extrema.
   */
-  JsonFormatLocaleFile(file,"    \"colorspace\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"colorspace\": %s,\n",
     CommandOptionToMnemonic(MagickColorspaceOptions,(ssize_t)
     image->colorspace));
   channel_statistics=(ChannelStatistics *) NULL;
@@ -1363,7 +1392,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
   if (image->error.normalized_maximum_error != 0.0)
     (void) FormatLocaleFile(file,"    \"normalizedMaximumError\": \"%g\",\n",
       image->error.normalized_maximum_error);
-  JsonFormatLocaleFile(file,"    \"renderingIntent\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"renderingIntent\": %s,\n",
     CommandOptionToMnemonic(MagickIntentOptions,(ssize_t)
     image->rendering_intent));
   if (image->gamma != 0.0)
@@ -1406,11 +1435,11 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
   (void) FormatLocaleFile(file,"    \"borderColor\": \"%s\",\n",color);
   GetColorTuple(&image->transparent_color,MagickTrue,color);
   (void) FormatLocaleFile(file,"    \"transparentColor\": \"%s\",\n",color);
-  JsonFormatLocaleFile(file,"    \"interlace\": %s,\n",CommandOptionToMnemonic(
+  JSONFormatLocaleFile(file,"    \"interlace\": %s,\n",CommandOptionToMnemonic(
     MagickInterlaceOptions,(ssize_t) image->interlace));
-  JsonFormatLocaleFile(file,"    \"intensity\": %s,\n",CommandOptionToMnemonic(
+  JSONFormatLocaleFile(file,"    \"intensity\": %s,\n",CommandOptionToMnemonic(
     MagickPixelIntensityOptions,(ssize_t) image->intensity));
-  JsonFormatLocaleFile(file,"    \"compose\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"compose\": %s,\n",
     CommandOptionToMnemonic(MagickComposeOptions,(ssize_t) image->compose));
   if ((image->page.width != 0) || (image->page.height != 0) ||
       (image->page.x != 0) || (image->page.y != 0))
@@ -1422,7 +1451,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
   if ((image->page.x != 0) || (image->page.y != 0))
     (void) FormatLocaleFile(file,"    \"originGeometry\": %+.20g%+.20g,\n",
       (double) image->page.x,(double) image->page.y);
-  JsonFormatLocaleFile(file,"    \"dispose\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"dispose\": %s,\n",
     CommandOptionToMnemonic(MagickDisposeOptions,(ssize_t) image->dispose));
   if (image->delay != 0)
     (void) FormatLocaleFile(file,"    \"delay\": \"%.20gx%.20g\",\n",
@@ -1437,17 +1466,17 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
     if (image->scene != 0)
       (void) FormatLocaleFile(file,"    \"scene\": %.20g,\n",(double)
         image->scene);
-  JsonFormatLocaleFile(file,"    \"compression\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"compression\": %s,\n",
     CommandOptionToMnemonic(MagickCompressOptions,(ssize_t)
     image->compression));
   if (image->quality != UndefinedCompressionQuality)
     (void) FormatLocaleFile(file,"    \"quality\": %.20g,\n",(double)
       image->quality);
-  JsonFormatLocaleFile(file,"    \"orientation\": %s,\n",
+  JSONFormatLocaleFile(file,"    \"orientation\": %s,\n",
     CommandOptionToMnemonic(MagickOrientationOptions,(ssize_t)
     image->orientation));
   if (image->montage != (char *) NULL)
-    JsonFormatLocaleFile(file,"    \"montage\": \"%s\",\n",image->montage);
+    JSONFormatLocaleFile(file,"    \"montage\": \"%s\",\n",image->montage);
   if (image->directory != (char *) NULL)
     {
       Image
@@ -1477,7 +1506,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
           q++;
         (void) CopyMagickString(image_info->filename,p,(size_t) (q-p+1));
         p=q+1;
-        JsonFormatLocaleFile(file,"{\n       \"name\": %s",
+        JSONFormatLocaleFile(file,"{\n       \"name\": %s",
           image_info->filename);
         handler=SetWarningHandler((WarningHandler) NULL);
         tile=ReadImage(image_info,exception);
@@ -1495,9 +1524,9 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
         property=GetNextImageProperty(tile);
         while (property != (const char *) NULL)
         {
-          JsonFormatLocaleFile(file,",\n       %s: ",property);
+          JSONFormatLocaleFile(file,",\n       %s: ",property);
           value=GetImageProperty(tile,property,exception);
-          JsonFormatLocaleFile(file,"%s",value);
+          JSONFormatLocaleFile(file,"%s",value);
           property=GetNextImageProperty(tile);
         }
         tile=DestroyImage(tile);
@@ -1529,9 +1558,9 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
       {
         if (n++ != 0)
           (void) FormatLocaleFile(file,",\n");
-        JsonFormatLocaleFile(file,"      %s: ",property);
+        JSONFormatLocaleFile(file,"      %s: ",property);
         value=GetImageProperty(image,property,exception);
-        JsonFormatLocaleFile(file,"%s",value);
+        JSONFormatLocaleFile(file,"%s",value);
         property=GetNextImageProperty(image);
       }
       (void) FormatLocaleFile(file,"\n    },\n");
@@ -1543,7 +1572,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
       /*
         Display clipping path.
       */
-      JsonFormatLocaleFile(file,"    \"clipping path\": %s,\n",value);
+      JSONFormatLocaleFile(file,"    \"clipping path\": %s,\n",value);
     }
   ResetImageProfileIterator(image);
   name=GetNextImageProfile(image);
@@ -1567,7 +1596,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
           continue;
         if (n++ != 0)
           (void) FormatLocaleFile(file,",\n");
-        JsonFormatLocaleFile(file,"      %s: {\n",name);
+        JSONFormatLocaleFile(file,"      %s: {\n",name);
         if (LocaleCompare(name,"iptc") == 0)
           EncodeIptcProfile(file,profile);
         (void) FormatLocaleFile(file,"        \"length\": \"%.20g\"",(double)
@@ -1593,9 +1622,9 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
       {
         if (n++ != 0)
           (void) FormatLocaleFile(file,",\n");
-        JsonFormatLocaleFile(file,"      %s: ",artifact);
+        JSONFormatLocaleFile(file,"      %s: ",artifact);
         value=GetImageArtifact(image,artifact);
-        JsonFormatLocaleFile(file,"%s",value);
+        JSONFormatLocaleFile(file,"%s",value);
         artifact=GetNextImageArtifact(image);
       }
       (void) FormatLocaleFile(file,"\n    },\n");
@@ -1616,10 +1645,10 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
       {
         if (n++ != 0)
           (void) FormatLocaleFile(file,",\n");
-        JsonFormatLocaleFile(file,"      %s: ",registry);
+        JSONFormatLocaleFile(file,"      %s: ",registry);
         value=(const char *) GetImageRegistry(StringRegistryType,registry,
           exception);
-        JsonFormatLocaleFile(file,"%s",value);
+        JSONFormatLocaleFile(file,"%s",value);
         registry=GetNextImageRegistry();
       }
       (void) FormatLocaleFile(file,"    },\n");
@@ -1628,22 +1657,22 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
     image->taint != MagickFalse ? "true" : "false");
   (void) FormatMagickSize(GetBlobSize(image),MagickFalse,"B",MagickPathExtent,
     format);
-  JsonFormatLocaleFile(file,"    \"filesize\": %s,\n",format);
+  JSONFormatLocaleFile(file,"    \"filesize\": %s,\n",format);
   (void) FormatMagickSize((MagickSizeType) image->columns*image->rows,
     MagickFalse,"B",MagickPathExtent,format);
   if (strlen(format) > 1)
     format[strlen(format)-1]='\0';
-  JsonFormatLocaleFile(file,"    \"numberPixels\": %s,\n",format);
+  JSONFormatLocaleFile(file,"    \"numberPixels\": %s,\n",format);
   (void) FormatMagickSize((MagickSizeType) ((double) image->columns*image->rows/
     elapsed_time+0.5),MagickFalse,"B",MagickPathExtent,format);
-  JsonFormatLocaleFile(file,"    \"pixelsPerSecond\": %s,\n",format);
+  JSONFormatLocaleFile(file,"    \"pixelsPerSecond\": %s,\n",format);
   (void) FormatLocaleFile(file,"    \"userTime\": \"%0.3fu\",\n",user_time);
   (void) FormatLocaleFile(file,"    \"elapsedTime\": \"%lu:%02lu.%03lu\",\n",
     (unsigned long) (elapsed_time/60.0),(unsigned long) ceil(fmod(
     elapsed_time,60.0)),(unsigned long) (1000.0*(elapsed_time-floor(
     elapsed_time))));
   url=GetMagickHomeURL();
-  JsonFormatLocaleFile(file,"    \"version\": %s\n",url);
+  JSONFormatLocaleFile(file,"    \"version\": %s\n",url);
   url=DestroyString(url);
   (void) FormatLocaleFile(file,"  }\n}\n");
   (void) fflush(file);