This is XImageURL.m in view mode; [Download] [Up]
/* -*-C-*- ******************************************************************************* * * File: XImageURL.m * RCS: /usr/local/sources/CVS/EnhanceMail/XImageURL.m,v 1.6 1998/06/27 00:58:28 tom Exp * Description: * Author: Carl Edman * Created: Fri Oct 20 14:47:00 1995 * Modified: Mon Jun 24 10:26:29 1996 (Carl Edman) cedman@capitalist.princeton.edu * Language: C * Package: N/A * Status: Experimental (Do Not Distribute) * * (C) Copyright 1995, but otherwise this file is perfect freeware. * ******************************************************************************* */ #import <libc.h> #import "EnhanceMail.h" #import "XImageURL.h" #import "Preferences.h" #import "SimpleString.h" #import "regexp.h" #include <netdb.h> #define MSG_OPEN_EXTERNAL_ATTACHMENT NXLoadLocalizedStringFromTableInBundle("Alerts", nil, "Open External Attachment", NULL) #define MSG_RETRIEVE_HTTP NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "Retrieving %s from %s via http...", NULL, Message for HTTP retrieval) #define LOCALCOPY(to,from,len) { to=alloca(len+1); strncpy(to,from,len); to[len]='\0'; } BOOL imagepathExpanded = NO; static const char *imagepath[]= { "/tmp", "~/Library/Mail/Images", "/LocalLibrary/Mail/Images", "/NextLibrary/Mail/Images", "#/Images", 0 }; @implementation NXImage(XImageURL) + (BOOL)grabURL:(const char *)url to:(const char *)localpath { static regexp *ftprx=0; static regexp *httprx=0; BOOL proxy=NO; if (!url || !*url) return NO; if (ftprx==0) ftprx=regcomp("^ftp://([^:/ ]*(:[^/@ ]*)?@)?([^/]*/)(([^/]*/)*)([^/;]*)$"); if (httprx==0) httprx=regcomp("^http://([^:/ ]*)(:[0-9]+)?(/[^;]*)$"); // For now, assume HTTP proxy also proxies ftp requests. if (EnhanceHTTPProxy && *EnhanceHTTPProxy) proxy=YES; if (!proxy && regexec(ftprx,url)) { char *host,*dir,*filename,*user,*pass,*userpass,*path; id fetcher=[MimeFetcher new]; if (ftprx->startp[1]&&ftprx->startp[2]) { LOCALCOPY(user,ftprx->startp[1],ftprx->startp[2]-ftprx->startp[1]); LOCALCOPY(pass,ftprx->startp[2]+1,ftprx->endp[2]-ftprx->startp[2]-1); userpass=alloca(strlen(user)+strlen(pass)+2); sprintf(userpass,"%s %s",user,pass); } else if (ftprx->startp[1]) { LOCALCOPY(user,ftprx->startp[1],ftprx->endp[1]-ftprx->startp[1]-1); if (pass=index([fetcher anonUserPass],' ')) pass++; else pass="anonymous"; userpass=alloca(strlen(user)+strlen(pass)+2); sprintf(userpass,"%s %s",user,pass); } else { const char *c=[fetcher anonUserPass]; userpass=strcpy(alloca(strlen(c)+1),c); } LOCALCOPY(host, ftprx->startp[3],ftprx->endp[3]-ftprx->startp[3]-1); LOCALCOPY(dir, ftprx->startp[4],ftprx->endp[4]-ftprx->startp[4]-1); LOCALCOPY(filename,ftprx->startp[6],ftprx->endp[6]-ftprx->startp[6]); LOCALCOPY(path,localpath,strlen(localpath)); if ([fetcher ftpFrom:host directory:dir filename:filename mode:"binary" forUserPass:userpass to:path]==NO) return NO; if (access(path,R_OK)!=0) return NO; return YES; } if (regexec(httprx,url) || (proxy && regexec(ftprx,url))) { char *hostname="localhost",*path="/",*port="80"; char buf[1024],*pos; struct sockaddr_in http; struct hostent *hp; int totlen=-1,rcvlen=0,len; int ifd=-1,ofd=-1; BOOL success=NO; BOOL httpseen=NO; Progressor *progress=nil; if (proxy) { // Allow different forms of proxy spec. if (!regexec(httprx,EnhanceHTTPProxy)) { sprintf(buf,"%s/",EnhanceHTTPProxy); if (!regexec(httprx,buf)) { sprintf(buf,"http://%s/",EnhanceHTTPProxy); if (!regexec(httprx,buf)) goto httpend; } } } if (httprx->startp[1]) LOCALCOPY(hostname,httprx->startp[1],httprx->endp[1]-httprx->startp[1]); if (httprx->startp[2]) LOCALCOPY(port,httprx->startp[2]+1,httprx->endp[2]-httprx->startp[2]-1); if (proxy) path=(char *)url; else if (httprx->startp[3]) LOCALCOPY(path,httprx->startp[3],httprx->endp[3]-(httprx->startp[3])); sprintf(buf,MSG_RETRIEVE_HTTP,strrchr(path,'/')+1,hostname); if ((progress=[Progressor newWithTitle:MSG_OPEN_EXTERNAL_ATTACHMENT message:buf])==nil) goto httpend; [progress setShowProgress:NO]; [progress beginModalSession]; if ((hp = gethostbyname(hostname)) == NULL) { // A numeric internet address, maybe? struct in_addr addr; if ((addr.s_addr = inet_addr(hostname)) == -1 || (hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == NULL) { goto httpend; } } bzero((char *)&http, sizeof(http)); bcopy(hp->h_addr,(char *)&http.sin_addr,hp->h_length); http.sin_family = hp->h_addrtype; http.sin_port = htons(atoi(port)); if ((ifd=socket(AF_INET, SOCK_STREAM, 0))==-1) goto httpend; if (connect(ifd,(struct sockaddr *) &http,sizeof(http))==-1) goto httpend; sprintf(buf,"GET %s HTTP/1.0\r\nUser-Agent: EnhanceMail/%s\r\nAccept: image/tiff\r\n\r\n",path,EnhanceVersion); write(ifd,buf,strlen(buf)); pos=buf; while(![progress cancelled]&&((len=read(ifd,pos,(buf+sizeof(buf))-pos))>0)) { char *end=pos+len,*c,*d; for(c=buf,d=buf;c<end;c++) { if (*c!='\n') continue; c[0]='\0'; if ((c>buf)&&(c[-1]=='\r')) c[-1]='\0'; if (strncasecmp(d,"HTTP/1.0 ",5)==0) // [sic] Allow version != 1.0 { if (atoi(d+9)!=200) goto httpend; httpseen=YES; } if (strncasecmp(d,"Content-Length: ",16)==0) { totlen=atoi(d+16); [progress setMinValue:0]; [progress setMaxValue:totlen]; [progress setProgress:0]; [progress setShowProgress:YES]; } if (*d=='\0') { if (!httpseen) goto httpend; if ((ofd=open(localpath,O_WRONLY|O_CREAT|O_TRUNC,0644))==-1) goto httpend; rcvlen=end-(c+1); write(ofd,c+1,end-(c+1)); [progress setProgress:rcvlen]; while(![progress cancelled]&&((len=read(ifd,buf,sizeof(buf)))>0)) { write(ofd,buf,len); rcvlen+=len; if (totlen>0) [progress setProgress:rcvlen]; } success=(len==0)&&((totlen==rcvlen)||(totlen==-1)); goto httpend; } d=c+1; } pos=buf; if (d>buf) while (d<end) *pos++=*d++; } httpend: if (ifd!=-1) close(ifd); if (ofd!=-1) close(ofd); if (progress!=nil) { if ([progress cancelled]) unlink(localpath); [progress endModalSession]; } return success; } return NO; } + (BOOL)grabURL:(const char *)url buffer:(char *)path { int i; char *localname; if (!(url && *url)) return NO; localname = alloca(3*strlen(url)+1); // Should be enough... [EnhanceXImageAliases getPathName:localname forURL:url]; if (imagepathExpanded==NO) imagepathExpanded=EnhancePaths(imagepath); for(i=0;imagepath[i];i++) { sprintf(path,"%s/%s",imagepath[i],localname); if (access(path,R_OK)==0) return YES; } /* Ignore last path (assume it is Image dir in bundle; don't want to store mugshots in there.) */ for (i-=2;i>=0;i--) if (access(imagepath[i],R_OK|W_OK|X_OK)==0) break; if (i<0) return NO; sprintf(path,"%s/%s",imagepath[i],localname); if (![self grabURL:url to:path]) { int fd=open(path,O_WRONLY|O_CREAT|O_TRUNC,0644); if (fd!=-1) close(fd); return NO; } return YES; } + (BOOL)grabURL:(const char *)url string:(SimpleString *)s { int fd; char path[MAXPATHLEN+1]; if (tmpnam(path)==0) return NO; if (![self grabURL:url to:path]) return NO; if ((fd=open(path,O_RDONLY))==-1) return NO; unlink(path); [s appendFile:fd]; close(fd); return YES; } - initURL:(const char *)url { char path[MAXPATHLEN+1]; struct stat buf; if (![[self class] grabURL:url buffer:path]) return [self free]; if ((stat(path,&buf)==-1)||(buf.st_size==0)) return [self free]; return [self initFromFile:path]; } - initNameInPath:(const char *)filename { int i; char path[MAXPATHLEN+1]; struct stat buf; if (imagepathExpanded==NO) imagepathExpanded=EnhancePaths(imagepath); for(i=0;imagepath[i];i++) { sprintf(path,"%s/%s",imagepath[i],filename); if (access(path,R_OK)==0) break; } if (!imagepath[i]) return [self free]; if ((stat(path,&buf)==-1)||(buf.st_size==0)) return [self free]; return [self initFromFile:path]; } @end // NXImage(XImageURL) @implementation EnhanceXImageAliases(XImageURL) + (EnhanceXImageAliases *)aliases { static id aliases; int i; if (aliases) return aliases; // XXX reuse by copy/paste. if (imagepathExpanded==NO) imagepathExpanded=EnhancePaths(imagepath); for (i = 0; imagepath[i]; i++) ; /* Ignore last path (assume it is Image dir in bundle; don't want to store mugshots in there.) */ for (i -= 2; i >= 0; i--) if (access(imagepath[i],R_OK|W_OK|X_OK)==0) break; if (i<0) return nil; aliases = [EnhanceXImageAliases aliasesForDirectory:imagepath[i]]; return aliases; } @end // EnhanceXImageAliases(XImageURL)
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.