Subversion Repositories filter_foundry

Rev

Rev 85 | Rev 107 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.     Copyright (C) 2003-5 Toby Thain, toby@telegraphics.com.au
  4.  
  5.     This program 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; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include <stddef.h>
  21.  
  22. #include "ff.h"
  23. #include "symtab.h"
  24.  
  25. #include "PIActions.h"
  26.  
  27. #include "compat_string.h"
  28.  
  29. long event_id;
  30.  
  31. /*
  32. Find a printable 4-character key, remembering (see PS API guide):
  33. All IDÕs starting with an uppercase letter are reserved by Adobe.
  34. All IDÕs that are all uppercase are reserved by Apple.
  35. All IDÕs that are all lowercase are reserved by Apple.
  36. This leaves all IDÕs that begin with a lowercase letter and have at least
  37. one uppercase letter for you and other plug-in developers.
  38. */
  39. unsigned long printablehash(unsigned long hash){
  40.         unsigned long key = 'a' + (hash % 26);  hash /= 26; // first lower case
  41.         key =   (key<<8) | (' ' + (hash % 95)); hash /= 95; // any printable
  42.         key =   (key<<8) | (' ' + (hash % 95)); hash /= 95; // any printable
  43.         return  (key<<8) | ('A' + (hash % 26));             // last upper case
  44. }
  45.  
  46. long fixpipl(PIPropertyList *pipl,long origsize,StringPtr title){
  47.         PIProperty *prop;
  48.         char *p;
  49.         struct hstm_data{
  50.                 /* this structure must be 14+1 bytes long, to match PiPL structure */
  51.                 long version; /* = 0 */
  52.                 long class_id;
  53.                 long event_id;
  54.                 short aete_resid;
  55.                 char scope[1];
  56.         };
  57.         struct hstm_data *hstm;
  58.         int scopelen;
  59.         unsigned long hash;
  60.  
  61.         pipl->count += 3; // more keys in PiPL
  62.  
  63.         p = (char*)pipl + origsize;
  64.         prop = (PIProperty*)p;
  65.  
  66.         /* add Title/Name property key */
  67.  
  68.         prop->vendorID = kPhotoshopSignature;
  69.         prop->propertyKey = PINameProperty;
  70.         prop->propertyID = 0;
  71.         prop->propertyLength = title[0]+1;
  72.         PLstrcpy((StringPtr)prop->propertyData,title);
  73.  
  74.         // skip past new property record, and any padding
  75.         p += (offsetof(PIProperty,propertyData) + prop->propertyLength + 3) & -4;
  76.         prop = (PIProperty*)p;
  77.  
  78.         /* add Category property key */
  79.  
  80.         prop->vendorID = kPhotoshopSignature;
  81.         prop->propertyKey = PICategoryProperty;
  82.         prop->propertyID = 0;
  83.         prop->propertyLength = gdata->parm.category[0]+1;
  84.         PLstrcpy((StringPtr)prop->propertyData,gdata->parm.category);
  85.  
  86.         p += (offsetof(PIProperty,propertyData) + prop->propertyLength + 3) & -4;
  87.         prop = (PIProperty*)p;
  88.  
  89.         /* add HasTerminology property key */
  90.  
  91.         /* construct scope string by concatenating Category and Title - hopefully unique! */
  92.         hstm = (struct hstm_data*)prop->propertyData;
  93.         scopelen = sprintf(hstm->scope,"%s %s",
  94.                                            INPLACEP2CSTR(gdata->parm.category),
  95.                                            INPLACEP2CSTR(title));
  96.  
  97.         /* make up a new event ID for this aete, based on printable base-95 hash of scope */
  98.         hash = djb2(hstm->scope);
  99.         event_id = printablehash(hash); /* this is used by fix_aete later... */
  100.  
  101.         prop->vendorID = kPhotoshopSignature;
  102.         prop->propertyKey = PIHasTerminologyProperty;
  103.         prop->propertyID = 0;
  104.         prop->propertyLength = offsetof(struct hstm_data,scope) + scopelen + 1;
  105.         hstm->version = 0;
  106.         hstm->class_id = plugInClassID;
  107.         hstm->event_id = event_id;
  108.         hstm->aete_resid = AETE_ID;
  109.  
  110.         p += (16+prop->propertyLength+3) & -4;
  111.  
  112.         return p - (char*)pipl;  // figure how many bytes were added
  113. }
  114.  
  115. /* Mac aete resources include word alignments after string pairs; Windows ones apparently don't */
  116. #ifdef MAC_ENV
  117.         #define ALIGNWORD(j) (j += j & 1)
  118. #else
  119.         #define ALIGNWORD(j)
  120. #endif
  121. #define SKIP_PSTR(j) (j += 1+aete[j])
  122.  
  123. long fixaete(unsigned char *aete,long origsize,StringPtr title){
  124.         int offset,oldlen,newlen,desclen,oldpad,newpad;
  125.         Str255 desc;
  126.  
  127.         offset = 8; /* point at suite name */
  128.  
  129.         SKIP_PSTR(offset); /* skip suite name (vendor) [maybe this should become author??] */
  130.         SKIP_PSTR(offset); /* skip suite description [set this from dialog field??] */
  131.         ALIGNWORD(offset);
  132.         offset += 4+2+2+2; /* offset now points to filter name. */
  133.  
  134.         oldlen = aete[offset];
  135.         newlen = title[0];
  136.  
  137.         /* shift aete data taking into account new title string */
  138.         desclen = aete[offset+1+oldlen];
  139.         PLstrcpy(desc,(StringPtr)(aete+offset+1+oldlen));  /* save description string... */
  140. #ifdef MAC_ENV
  141.         /* see if alignment padding is necessary */
  142.         oldpad = (oldlen + desclen) & 1;
  143.         newpad = (newlen + desclen) & 1;
  144. #else
  145.         oldpad = newpad = 0;
  146. #endif
  147.         /* shift latter part of aete data, taking into account new string lengths */
  148.         memcpy(aete+offset+1+newlen+newpad,
  149.                    aete+offset+1+oldlen+oldpad,
  150.                    origsize-offset-1-oldlen-oldpad); /* phew! */
  151.         /* copy in new title string */
  152.         PLstrcpy((StringPtr)(aete+offset),title);
  153.         /* copy description string into right place... [this could be new description from dialog field??] */
  154.         PLstrcpy((StringPtr)(aete+offset+1+newlen),desc);
  155.  
  156.         SKIP_PSTR(offset); /* skip (new) event name */
  157.         SKIP_PSTR(offset); /* skip event description */
  158.         ALIGNWORD(offset);
  159.  
  160.         /* set event ID */
  161.         *(unsigned long*)(aete+offset+4) = event_id; /* FIXME: this might be unaligned access on some platforms?? */
  162.  
  163.         return origsize-oldlen-oldpad+newlen+newpad;
  164. }
  165.  
  166. void obfusc(unsigned char *pparm,size_t size){
  167.         int i;
  168.         unsigned char *p;
  169.  
  170.         /* Do a small self-test to test if the stdlib implementation works as expected, i.e. that it only
  171.          * depends on the seed set by srand() and on nothing else.
  172.          */
  173.         srand(0xdc43df3c);
  174.         int selftest1 = rand();
  175.         int selftest2 = rand();
  176.         int selftest3 = rand();
  177.  
  178.         srand(0xdc43df3c);
  179.         if ((rand() != selftest1) || (rand() != selftest2) || (rand() != selftest3)) {
  180.                 // This should never happen
  181.                 simplealert("Stdcall rand() implementation does not work as expected. Obfuscation operation will be cancelled.");
  182.                 return; // apply no obfuscation
  183.         }
  184.  
  185.         /* Very simplistic. meant to hide from casual observation/loading only.
  186.          * Results are platform dependent, but this should not matter. */
  187.         srand(0xdc43df3c);
  188.         for(i = size, p = pparm; i--;)
  189.                 *p++ ^= rand();
  190. }
  191.