Subversion Repositories filter_foundry

Rev

Rev 515 | 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-2009 Toby Thain, toby@telegraphics.net
  4.     Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. #include <plstringfuncs.h>
  22. #include <ASRegistry.h>
  23. #include <ctype.h>
  24.  
  25. #include "ff.h"
  26.  
  27. #include "file_compat.h"
  28.  
  29. // MoreFiles headers
  30. #include "FileCopy.h"
  31. #include "MoreFilesExtras.h"
  32.  
  33. // prototype for a function included in Carbon's stdlib and declared in /usr/include/string.h
  34. // but missing from MPW Universal header string.h
  35. #ifndef _STRING_H_
  36.         char *strnstr(const char *, const char *, size_t);
  37. #endif
  38.  
  39. static OSErr doresources(FSSpec *srcplug, FSSpec *rsrccopy){
  40.         short srcrn,dstrn;
  41.         Handle hpipl,h;
  42.         long origsize,newsize,parm_type,parm_id;
  43.         OSErr e = noErr;
  44.         Str255 title, category;
  45.         long event_id;
  46.  
  47.         #ifdef MACMACHO
  48.         FSRef inref,outref;
  49.         // work with resources in data fork
  50.         if( !(e = FSpMakeFSRef(srcplug,&inref))
  51.          && !(e = FSOpenResourceFile(&inref,0/*forkNameLength*/,NULL/*forkName*/,fsRdPerm,&srcrn))
  52.          && ((e = FSpMakeFSRef(rsrccopy,&outref))
  53.                  || (e = FSOpenResourceFile(&outref,0/*forkNameLength*/,NULL/*forkName*/,fsWrPerm,&dstrn))) )
  54.                 CloseResFile(srcrn);
  55.         #else
  56.         // ordinary resource fork files
  57.         srcrn = FSpOpenResFile(srcplug,fsRdPerm);
  58.         if(srcrn != -1){
  59.                 dstrn = FSpOpenResFile(rsrccopy,fsWrPerm);
  60.                 if(dstrn == -1){
  61.                         e = ResError();
  62.                         CloseResFile(srcrn);
  63.                 }
  64.         }else e = ResError();
  65.         #endif
  66.  
  67.         if(!e){
  68.                 /* create a new PiPL resource for the standalone plugin,
  69.                    with updated title and category strings */
  70.  
  71.                 if( (hpipl = Get1Resource('tpLT',16000))
  72.                  && (h = Get1Resource('PiPL',16000)) )
  73.                 {
  74.                         RemoveResource(h);
  75.  
  76.                         DetachResource(hpipl);
  77.  
  78.                         myc2pstrcpy(title,gdata->parm.szTitle);
  79.                         if(gdata->parm.popDialog)
  80.                                 PLstrcat(title,"\pÉ");
  81.  
  82.                         myc2pstrcpy(category,gdata->parm.szCategory);
  83.  
  84.                         origsize = GetHandleSize(hpipl);
  85.                         SetHandleSize(hpipl,origsize+0x300); /* some slop for fixup to work with */
  86.                         HLock(hpipl);
  87.                         newsize = fixpipl((PIPropertyList*) *hpipl,origsize,title,gdata->parm.szCategory,category,&event_id);
  88.                         HUnlock(hpipl);
  89.                         SetHandleSize(hpipl,newsize);
  90.  
  91.                         AddResource(hpipl,'PiPL',16000,"\p");
  92.  
  93.                         /* convert C strings to Pascal strings */
  94.                         PARM_T pascal_parm = (PARM_T)malloc(sizeof(PARM_T));
  95.                         memcpy(pascal_parm, gdata->parm, sizeof(PARM_T));
  96.                         myc2pstr(pascal_parm->szCategory);
  97.                         myc2pstr(pascal_parm->szTitle);
  98.                         myc2pstr(pascal_parm->szCopyright);
  99.                         myc2pstr(pascal_parm->szAuthor);
  100.                         for (i = 0; i < 4; ++i)
  101.                                 myc2pstr(pascal_parm->szMap[i]);
  102.                         for (i = 0; i < 8; ++i)
  103.                                 myc2pstr(pascal_parm->szCtl[i]);
  104.  
  105.                         if( !(e = ResError()) ){
  106.                                 /* do a similar trick with the terminology resource,
  107.                                    so the scripting system can distinguish the standalone plugin */
  108.  
  109.                                 if( (h = Get1Resource(typeAETE,AETE_ID)) ){
  110.                                         SetHandleSize(h,4096);
  111.                                         HLock(h);
  112.                                         newsize = aete_generate((unsigned char*)*h, &pascal_parm, event_id);
  113.                                         HUnlock(h);
  114.                                         SetHandleSize(h,newsize);
  115.  
  116.                                         ChangedResource(h);
  117.  
  118.                                         if( !(e = ResError()) ){
  119.                                                 /* add PARM resource */
  120.                                                 if( !(e = PtrToHand(&pascal_parm,&h,sizeof(PARM_T))) ){
  121.                                                         if(gdata->obfusc){
  122.                                                                 HLock(h);
  123.                                                                 obfusc((PARM_T*)*h);
  124.                                                                 HUnlock(h);
  125.                                                                 parm_type = OBFUSCDATA_TYPE_NEW;
  126.                                                                 parm_id = OBFUSCDATA_ID_NEW;
  127.                                                         }else{
  128.                                                                 parm_type = PARM_TYPE;
  129.                                                                 parm_id = PARM_ID_NEW;
  130.                                                         }
  131.                                                         AddResource(h,parm_type,parm_id,"\p");
  132.                                                 }
  133.                                         }
  134.                                 }
  135.  
  136.                         }
  137.  
  138.                 }
  139.                 if(!e)
  140.                         e = ResError();
  141.  
  142.                 CloseResFile(dstrn);
  143.                 CloseResFile(srcrn);
  144.         }
  145.  
  146.         return e;
  147. }
  148.  
  149. static int copyletters(char *dst,char* src){
  150.         int i, n;
  151.  
  152.         for(i=0; i<strlen(src); ++i) {
  153.                 if(isalpha(src[i])){
  154.                         *dst++ = src[i];
  155.                         ++n;
  156.                 }
  157.         }
  158.  
  159.         return n;
  160. }
  161.  
  162. // Info.plist in new standalone copy needs to be edited -
  163. // at least the CFBundleIdentifier property must be unique
  164.  
  165. static OSErr copyplist(FSSpec *fss, short dstvol, long dstdir){
  166.         static char *key = "com.telegraphics.FilterFoundry";
  167.         static unsigned char *fname="\pInfo.plist";
  168.         char *buf,*save,*p;
  169.         short rn,dstrn,i,n,m;
  170.         FILEPOS eof;
  171.         FILECOUNT count;
  172.         OSErr e;
  173.  
  174.         if( !(e = HCreate(dstvol,dstdir,fname,'pled','TEXT')) ){
  175.                 if( !(e = HOpenDF(dstvol,dstdir,fname,fsWrPerm,&dstrn)) ){
  176.                         if( !(e = FSpOpenDF(fss,fsRdPerm,&rn)) ){
  177.                                 if( !(e = GetEOF(rn,&eof)) && (buf = malloc(eof+1024)) ){
  178.                                         if( !(e = FSRead(rn,&eof,buf)) ){
  179.                                                 buf[eof] = 0;
  180.                                                 if( (p = strnstr(buf,key,eof)) && (save = malloc(eof-(p-buf)+1)) ){
  181.                                                         p += strlen(key);
  182.                                                         // store text after matched string
  183.                                                         strcpy(save,p);
  184.  
  185.                                                         *p++ = '.';
  186.                                                         n = copyletters(p,gdata->parm.szCategory);
  187.                                                         p += n;
  188.                                                         if(n) *p++ = '.';
  189.                                                         m = copyletters(p,gdata->parm.szTitle);
  190.                                                         p += m;
  191.                                                         if(!m){
  192.                                                                 // generate a random ASCII identifier
  193.                                                                 srand(TICKCOUNT());
  194.                                                                 for(i = 8; i--;)
  195.                                                                         *p++ = 'a' + (rand() % 26);
  196.                                                         }
  197.                                                         strcpy(p,save);
  198.  
  199.                                                         count = strlen(buf);
  200.                                                         e = FSWrite(dstrn,&count,buf);
  201.  
  202.                                                         free(save);
  203.                                                 }else e = paramErr; // not found?? shouldn't happen
  204.                                         }
  205.                                         free(buf);
  206.                                 }
  207.                                 FSClose(rn);
  208.                         }
  209.                         FSClose(dstrn);
  210.                 }
  211.                 if(e) HDelete(dstvol,dstdir,fname);
  212.         }
  213.         return e;
  214. }
  215.  
  216. static OSErr make_bundle(StandardFileReply *sfr, short plugvol,
  217.                                                  long plugdir, StringPtr plugname, char *reason)
  218. {
  219.         short dstvol = sfr->sfFile.vRefNum;
  220.         long bundledir,contentsdir,macosdir,rsrcdir;
  221.         DInfo fndrInfo;
  222.         OSErr e;
  223.         FSSpec fss,macosfss,rsrcfss,rsrccopyfss;
  224.         char *why;
  225.  
  226.         if( !(e = FSpDirCreate(&sfr->sfFile,sfr->sfScript,&bundledir)) ){
  227.                 if(!(e = FSpGetDInfo(&sfr->sfFile,&fndrInfo)) ){
  228.                         fndrInfo.frFlags |= kHasBundle;
  229.                         FSpSetDInfo(&sfr->sfFile,&fndrInfo);
  230.                 }
  231.                 if( !(e = DirCreate(dstvol,bundledir,"\pContents",&contentsdir)) ){
  232.                         if( !(e = DirCreate(dstvol,contentsdir,"\pMacOS",&macosdir)) ){
  233.                                 if( !(e = DirCreate(dstvol,contentsdir,"\pResources",&rsrcdir)) ){
  234.                                         /* copy the Info.plist file, resource file, and executable */
  235.                                         if( !(e = FSMakeFSSpec(plugvol,plugdir,"\p::MacOS:FilterFoundry",&macosfss))
  236.                                          && !(e = FileCopy(macosfss.vRefNum,macosfss.parID,macosfss.name, dstvol,macosdir,NULL, NULL,NULL,0,false)) )
  237.                                         {
  238.                                                 /* add PARM resources to each binary, and edit PiPLs */
  239.                                                 if( !(e = FSMakeFSSpec(plugvol,plugdir,"\p::Resources:FilterFoundry.rsrc",&rsrcfss))
  240.                                                  && !(e = FileCopy(rsrcfss.vRefNum,rsrcfss.parID,rsrcfss.name, dstvol,rsrcdir,NULL, NULL,NULL,0,false))
  241.                                                  && !(e = FSMakeFSSpec(dstvol,rsrcdir,"\pFilterFoundry.rsrc",&rsrccopyfss)) )
  242.                                                 {
  243.                                                         if( !(e = doresources(&rsrcfss, &rsrccopyfss))
  244.                                                          && !(e = FSMakeFSSpec(plugvol,plugdir,"\p::Info.plist",&fss)) )
  245.                                                         {
  246.                                                                 e = copyplist(&fss,dstvol,contentsdir);
  247.                                                                 if(e){
  248.                                                                         FSpDelete(&rsrccopyfss);
  249.                                                                         why = "Can't copy Info.plist file.";
  250.                                                                 }
  251.                                                         }else why = "Can't copy resources.";
  252.                                                         if(e) HDelete(dstvol,macosdir,"\pFilterFoundry");
  253.                                                 }else why = "Can't copy FilterFoundry.rsrc file.";
  254.                                                 if(e) HDelete(dstvol,rsrcdir,plugname);
  255.                                         }else why = "Can't copy FilterFoundry executable.";
  256.                                         if(e) HDelete(dstvol,contentsdir,"\pResources");
  257.                                 }else why = "Can't create bundle Contents/Resources directory.";
  258.                                 if(e) HDelete(dstvol,contentsdir,"\pMacOS");
  259.                         }else why = "Can't create bundle Contents/MacOS directory.";
  260.                         if(e) HDelete(dstvol,bundledir,"\pContents");
  261.                 }else why = "Can't create bundle Contents directory.";
  262.                 if(e) FSpDelete(&sfr->sfFile);
  263.         }else why = "Can't create new bundle directory.";
  264.  
  265.         if(e)
  266.                 sprintf(reason, "%s (%d)", why, e);
  267.         else
  268.                 reason[0] = 0;
  269.  
  270.         return e;
  271. }
  272.  
  273. static OSErr make_singlefile(StandardFileReply *sfr, short plugvol, long plugdir, StringPtr plugname){
  274.         OSErr e;
  275.         FSSpec origfss;
  276.  
  277.         e = FSpDelete(&sfr->sfFile);
  278.         if(e && e != fnfErr){
  279.                 alertuser(_strdup("Can't replace the existing file. Try a different name or location."),_strdup(""));
  280.                 return userCanceledErr;
  281.         }
  282.  
  283.         if( !(e = FileCopy(plugvol,plugdir,plugname, sfr->sfFile.vRefNum,sfr->sfFile.parID,NULL, sfr->sfFile.name,NULL,0,false))
  284.          && !(e = FSMakeFSSpec(plugvol,plugdir,plugname,&origfss)) )
  285.                 /* add PARM resources, and edit PiPL */
  286.                 e = doresources(&origfss, &sfr->sfFile);
  287.  
  288.         return e;
  289. }
  290.  
  291. OSErr make_standalone(StandardFileReply *sfr){
  292.         OSErr e;
  293.         short plugvol;
  294.         long plugdir;
  295.         Str255 plugname;
  296.         char reason[0x100] = {0};
  297.  
  298.         if(!(e = GetFileLocation(CurResFile(),&plugvol,&plugdir,plugname))){
  299.                 #ifdef MACMACHO
  300.                 e = make_bundle(sfr,plugvol,plugdir,plugname,reason);
  301.                 #else
  302.                 e = make_singlefile(sfr,plugvol,plugdir,plugname);
  303.                 #endif
  304.         }
  305.  
  306.         if(e && e != userCanceledErr) {
  307.                 alertuser(_strdup("Could not create standalone plugin."),reason);
  308.         } else {
  309.                 showmessage(_strdup("Filter was sucessfully created"));
  310.         }
  311.  
  312.         return e;
  313. }
  314.