Пример #1
0
/*
 * Make all the directories specified in the path
 */
int XP_MakeDirectoryR(const char* name, XP_FileType type)
{
    char separator;
    int result = 0;
    char * finalName;

#if defined(XP_WIN) || defined(XP_OS2)
    separator = '\\';
#elif defined XP_UNIX
    separator = '/';
#endif
    finalName = WH_FileName(name, type);
    if ( finalName )
    {
        char * dirPath;
        char * currentEnd;
        int err = 0;
        XP_StatStruct s;
        dirPath = XP_STRDUP( finalName );
        if (dirPath == NULL)
            return -1;

        currentEnd = XP_STRCHR(dirPath, separator);
        /* Loop through every part of the directory path */
        while (currentEnd != 0)
        {
            char savedChar;
            savedChar = currentEnd[1];
            currentEnd[1] = 0;
            if ( XP_Stat(dirPath, &s, xpURL ) != 0)
                err = XP_MakeDirectory(dirPath, xpURL);
            if ( err != 0)
            {
                XP_ASSERT( FALSE );	/* Could not create the directory? */
                break;
            }
            currentEnd[1] = savedChar;
            currentEnd = XP_STRCHR( &currentEnd[1], separator);
        }
        if ( err == 0 )
            /* If the path is not terminated with / */
        {
            if ( dirPath[XP_STRLEN( dirPath) - 1] != separator )
                if ( XP_Stat(dirPath, &s, xpURL ) != 0)
                    err = XP_MakeDirectory(dirPath, xpURL);
        }
        if ( 0 != err )
            result = err;
        if ( dirPath )
            XP_FREE( dirPath );
    }
    else
        result = -1;
    if ( finalName )
        XP_FREE( finalName );
    XP_ASSERT( result == 0 );	/* For debugging only */
    return result;
}
Пример #2
0
// create short icon label from full path/url
char *XFE_ComposeAttachFolderView::parseItemLabel(const char *url)
{
    // (alastair) code taken from libmsg/msgsend.cpp - be nice just to call into libmsg
    // modified slightly to avoid bug of trailing / generating empty name
    // modified to return truncated label for mail/news URL's

    if (!url || strlen(url)==0)
        return XP_STRDUP("(null)");

    char *s;
    char *s2;
    char *s3;
    
    /* If we know the URL doesn't have a sensible file name in it,
       don't bother emitting a content-disposition. */
    if (!strncasecomp (url, "news:", 5))
        return XP_STRDUP("news:");
    if (!strncasecomp (url, "snews:", 6))
        return XP_STRDUP("snews:");    
    if (!strncasecomp (url, "mailbox:", 8))
        return XP_STRDUP("mailbox:");

    char *tmpLabel = XP_STRDUP(url);

    s=tmpLabel;
    /* remove trailing / or \ */
    int len=strlen(s);
    if (s[len-1]=='/' || s[len-1]=='\\')
        s[len-1]='\0';
    
    s2 = XP_STRCHR (s, ':');
    if (s2) s = s2 + 1;
    /* Take the part of the file name after the last / or \ */
    s2 = XP_STRRCHR (s, '/');
    if (s2) s = s2+1;
    s2 = XP_STRRCHR (s, '\\');
    if (s2) s = s2+1;

    /* if it's a non-file url, strip off any named anchors or search data */
    if (XP_STRNCASECMP(url,"file:",5)!=0 && url[0]!='/') {
        /* Now trim off any named anchors or search data. */
        s3 = XP_STRCHR (s, '?');
        if (s3) *s3 = 0;
        s3 = XP_STRCHR (s, '#');
        if (s3) *s3 = 0;
    }

    /* Now lose the %XX crap. */
    NET_UnEscape (s);

    char *retLabel=XP_STRDUP(s);
    XP_FREE(tmpLabel);
    
    return retLabel;
}
Пример #3
0
/* FE should call XP_FindNamedAnchor before getting a URL 
 * that is going into an HTML window (output_format is FO_CACHE_AND_PRESENT
 *
 * if named anchor is found:
 * XP_FindNamedAnchor 
 *					- updates context history, and global history properly
 * if it is not found, we do not touch any arguments
 *
 * Usage:
 * In your GetURL routine
 * if (XP_FindNamedAnchor(context, url, &x, &y))
 *  {
 * 		SetDocPosition(x,y);
 *		if (url->history_num == 0)	// if you are not handling go back this way, do not do this
 *			SHIST_AddDocument( &fContext, SHIST_CreateHistoryEntry( url, he->title) );
 *		else
 *			SHIST_SetCurrent(&fContext->hist, url->history_num);
 *      SetURLTextField(url->address);
 *      SetURLTextFieldTitle( ... url->is_netsite ... );
 *		NET_FreeURLStruct(url);
 *      RegenerateHistoryMenuAndDialogBoxContents()
 *  }
 * else
 *		NET_GetURL
 */
Bool XP_FindNamedAnchor(MWContext * context, URL_Struct * url, 
							int32 *xpos, int32 *ypos)
{
	History_entry *he;
	
	if (!context)
		return FALSE;

	he = SHIST_GetCurrent (&context->hist);
	
	if (he
		&& he->address
		&& url
		&& url->address
		&& XP_STRCHR(url->address, '#') /* it must have a named hash */
		&& url->method == URL_GET_METHOD
		&& url->force_reload == NET_DONT_RELOAD
		&& LO_LocateNamedAnchor(context, url, xpos, ypos))
	{
		GH_UpdateGlobalHistory( url );
		/* don't do this - jwz. */
		/* NET_FreeURLStruct( url ); */
		return TRUE;
	}
	return FALSE;	
}
Пример #4
0
// nyi - extract nice file name from title or url
char *XFE_URLDesktopType::getFilename(int pos)
{
    if (pos<0 || pos>=_numItems || _url[pos]==NULL)
        return XP_STRDUP("unknown");

    // (alastair) code taken from libmsg/msgsend.cpp - be nice just to call into libmsg
    // modified slightly to avoid bug of trailing / generating empty name
    // modified to return truncated label for mail/news URL's

    const char *url=_url[pos];
    
    if (!url || strlen(url)==0)
        return XP_STRDUP("(null)");

    char *s;
    char *s2;
    char *s3;
   
    /* If we know the URL doesn't have a sensible file name in it,
       don't bother emitting a content-disposition. */
    if (!XP_STRNCASECMP(url, "news:", 5))
        return XP_STRDUP("news:");
    if (!XP_STRNCASECMP(url, "snews:", 6))
        return XP_STRDUP("snews:");
    if (!XP_STRNCASECMP(url, "mailbox:", 8))
        return XP_STRDUP("mailbox:");

    char *tmpLabel = XP_STRDUP(url);

    s=tmpLabel;
    /* remove trailing / or \ */
    int len=strlen(s);
    if (s[len-1]=='/' || s[len-1]=='\\')
        s[len-1]='\0';

    s2 = XP_STRCHR (s, ':');
    if (s2) s = s2 + 1;
    /* Take the part of the file name after the last / or \ */
    if (s2 = XP_STRRCHR (s, '/'))
        s = s2+1;
    else if (s2 = XP_STRRCHR (s, '\\'))
        s = s2+1;

    /* if it's a non-file url do some additional massaging */
    if (XP_STRNCASECMP(url,"file:",5)!=0 && url[0]!='/') {
        /* Trim off any named anchors or search data. */
        s3 = XP_STRCHR (s, '?');
        if (s3) *s3 = 0;
        s3 = XP_STRCHR (s, '#');
        if (s3) *s3 = 0;

        /* Check for redundant document name.
         * Use previous URL component to provide more meaningful file name.
         */
        if (s2 &&
            XP_STRCASECMP(s,"index.html")==0 ||
            XP_STRCASECMP(s,"index.htm")==0 ||
            XP_STRCASECMP(s,"index.cgi")==0 ||
            XP_STRCASECMP(s,"index.shtml")==0 ||
            XP_STRCASECMP(s,"home.html")==0 ||
            XP_STRCASECMP(s,"home.htm")==0 ||
            XP_STRCASECMP(s,"home.cgi")==0 ||
            XP_STRCASECMP(s,"home.shtml")==0) {
            /* Trim redundant component and try again */
            *s2='\0';
            s=tmpLabel;
            /* Redo: Take the part of the file name after the last / or \ */
            if (s2 = XP_STRRCHR (s, '/'))
                s = s2+1;
            else if (s2 = XP_STRRCHR (s, '\\'))
                s = s2+1;
        }
    }

    /* Now lose the %XX crap. */
    NET_UnEscape (s);

    char *retLabel=XP_STRDUP(s);
    XP_FREE(tmpLabel);

    return retLabel;
}
Пример #5
0
/* parse lines in an HTML help mapping file.
 * get window_size and name, etc...
 *
 * when the id is found function returns HTML_HELP_ID_FOUND
 * on error function returns negative error code.
 */
PRIVATE int
net_ParseHTMLHelpLine(HTMLHelpParseObj *obj, char *line_data)
{
	char *line = XP_StripLine(line_data);
	char *token;
	char *next_word;

	if(*line == '<')
	  {
		/* find and terminate the end '>' */
		XP_STRTOK(line, ">");

		token = XP_StripLine(line+1);

		if(!strncasecomp(token, 
						 ID_MAP_TOKEN, 
						 sizeof(ID_MAP_TOKEN)-1))
		  {
			obj->in_id_mapping = TRUE;
		  }
		else if(!strncasecomp(token, 
						 END_ID_MAP_TOKEN, 
						 sizeof(END_ID_MAP_TOKEN)-1))
		  {
			obj->in_id_mapping = FALSE;
		  }
		else if(!strncasecomp(token, 
						 FRAME_GROUP_TOKEN, 
						 sizeof(FRAME_GROUP_TOKEN)-1))
		  {
			char *cp = token + sizeof(FRAME_GROUP_TOKEN)-1;
			frame_set_struct * fgs = XP_NEW(frame_set_struct);

			while(isspace(*cp)) cp++;

			if(fgs)
			  {
				XP_MEMSET(fgs, 0, sizeof(frame_set_struct));

				next_word=NULL; /* init */

				do {
					if(!strncasecomp(cp, SRC_TOKEN, sizeof(SRC_TOKEN)-1))
				  	  {
						char *address = net_get_html_help_token(
														cp+sizeof(SRC_TOKEN)-1,
														&next_word);
						cp = next_word;
						fgs->address = XP_STRDUP(address);
				  	  }
					else if(!strncasecomp(cp, 
									  WINDOW_TOKEN, 
									  sizeof(WINDOW_TOKEN)-1))
				      {
					    char *window = net_get_html_help_token(
													cp+sizeof(WINDOW_TOKEN)-1, 
													&next_word);
					    cp = next_word;
					    fgs->target = XP_STRDUP(window);
				      }
					else
					  {
						/* unknown attribute.  Skip to next whitespace
						 */ 
						while(*cp && !isspace(*cp)) 
							cp++;


						if(*cp)
						  {
							while(isspace(*cp)) cp++;
							next_word = cp;
						  }
						else
						  {
							next_word = NULL;
						  }
					  }

				  } while(next_word);
			
				XP_ListAddObject(obj->frame_group_stack, fgs);
			  }
		  }
		else if(!strncasecomp(token, 
						 END_FRAME_GROUP_TOKEN, 
						 sizeof(END_FRAME_GROUP_TOKEN)-1))
		  {
			frame_set_struct *fgs;

			fgs = XP_ListRemoveTopObject(obj->frame_group_stack);

			if(fgs)
				net_help_free_frame_group_struct(fgs);
		  }
	  }
	else if(!obj->in_id_mapping)
	  {
		if(!strncasecomp(line, 
					 	WINDOW_SIZE_TOKEN, 
					 	sizeof(WINDOW_SIZE_TOKEN)-1))
		  {
			/* get window size */
			char *comma=0;
			char *window_size = net_get_html_help_token(line+
												sizeof(WINDOW_SIZE_TOKEN)-1, 
												NULL);

			if(window_size)
				comma = XP_STRCHR(window_size, ',');

			if(comma)
			  {
				*comma =  '\0';
				obj->window_width = XP_ATOI(window_size);
				obj->window_height = XP_ATOI(comma+1);
			  }
		  }
		else if(!strncasecomp(line, 
						 	WINDOW_NAME_TOKEN, 
						 	sizeof(WINDOW_NAME_TOKEN)-1))
		  {
			char *window_name = net_get_html_help_token(line+
												sizeof(WINDOW_NAME_TOKEN)-1,
												NULL);

			if(window_name)
			  {
				FREEIF(obj->window_name);
				obj->window_name = XP_STRDUP(window_name);
			  }
		  }
		else if(!strncasecomp(line, 
					 	HELP_VERSION_TOKEN, 
					 	sizeof(HELP_VERSION_TOKEN)-1))
		  {
			/* get window size */
			char *help_version = net_get_html_help_token(line+
												sizeof(HELP_VERSION_TOKEN)-1, 
												NULL);

			if(help_version)
			  {
				obj->helpVersion = XP_ATOI(help_version);
			  }
		  }
	  }
	else
	  {
		/* id mapping pair */
		if(!strncasecomp(line, obj->id, XP_STRLEN(obj->id)))
		  {
			char *id_value = net_get_html_help_token(line+XP_STRLEN(obj->id),
													 &next_word);

			if(id_value)
			  {
			  	obj->id_value = XP_STRDUP(id_value);

				while(next_word)
				  {
					char *cp = next_word;

                    if(!strncasecomp(cp,
                                     TARGET_TOKEN,
                                      sizeof(TARGET_TOKEN)-1))
                      {
                        char *target = net_get_html_help_token(
                                                    cp+sizeof(TARGET_TOKEN)-1,
                                                    &next_word);
                        cp = next_word;
                        obj->content_target = XP_STRDUP(target);
                      }
					else
					  {
                        /* unknown attribute.  Skip to next whitespace
                         */
                        while(*cp && !isspace(*cp))
                            cp++;

                        if(*cp)
                          {
                            while(isspace(*cp)) cp++;
                            next_word = cp;
                          }
                        else
                          {
                            next_word = NULL;
                          }
					  }
				  }
			  }
		
			return(HTML_HELP_ID_FOUND);
		  }
		if(!strncasecomp(line, DEFAULT_HELP_ID, sizeof(DEFAULT_HELP_ID)-1))
		  {
			char *default_id_value = net_get_html_help_token(
												line+sizeof(DEFAULT_HELP_ID)-1,
												NULL);

            if(default_id_value)
                obj->default_id_value = XP_STRDUP(default_id_value);
		  }
		
	  }

	return(0);
}
Пример #6
0
PUBLIC int
NET_ParseNetHelpURL(URL_Struct *URL_s)
{
	/* this is a nethelp: URL
	 * first, see if it's local or remote by checking for the @ 
	 */
	char *remote_addr_ptr = 0;
	char *remote_addr=0;
	char *topic_ptr = 0;
	char *topic = 0;
	char *scheme_specific = 0;
	char *pCharacter;

	XP_Bool appendProjFile = FALSE;
	
	remote_addr_ptr = XP_STRCHR(URL_s->address, '@');
	
	if (!remote_addr_ptr) {
		char *default_URL = 0;

		/* it's local, so we need to get the default, then append the project file */
		net_get_default_help_URL(&default_URL);
		
		if (default_URL) {
			StrAllocCopy(remote_addr, default_URL);
			XP_FREE(default_URL);
		}
		
		appendProjFile = TRUE;
		
	} else {
		*remote_addr_ptr = '\0';
		
		StrAllocCopy(remote_addr, remote_addr_ptr+1);

		if (remote_addr && (remote_addr[XP_STRLEN(remote_addr)] == '/')) {
		/* Check to see if the remote_addr ends in a slash.  If so, we
		   have some appending to do */

			appendProjFile = TRUE;
		}
	}

	if (!remote_addr) {
		/* We've obviously run into some kind of a memory problem here. */
		/* Time to bail */
		return MK_OUT_OF_MEMORY;
	}

	/* By now, the URL_s->address has been stripped of any location information */
	/* First, remove the scheme, which is guaranteed to be there. */
	
	scheme_specific = XP_STRCHR(URL_s->address, ':') + 1;
	
	topic_ptr = XP_STRCHR(scheme_specific, ':');
	
	if (!topic_ptr) {
		/* This is an error case, but we'll handle it anyway by defaulting to
		   the generic topic */
		   
		StrAllocCopy(topic, DEFAULT_HELP_ID);
	} else {
		*topic_ptr = '\0';
		StrAllocCopy(topic, topic_ptr+1);

	}		
	
	if (appendProjFile) {
		/* Now the URL_s->address will contain only the vendor/component information */
		
		/* In an act of incredible lameness, we want to lowercase the
		   vendor/component, since we say that these will default to 
		   lower case in the spec.
		   
		   FIXME!: Note that this may not be correct for double-byte encoded
		   characters, but the Intl team was unable to come up with a good
		   solution here; in general, we probably won't have any issue, since
		   URLs themselves should be in an ASCII-encoding (?).
		*/

		pCharacter = scheme_specific;

		while (*pCharacter)
		{
			*pCharacter = (char) XP_TO_LOWER((unsigned int) *pCharacter);
			pCharacter++;
		}

		
		StrAllocCat(remote_addr, scheme_specific);
		StrAllocCat(remote_addr, DEFAULT_HELP_PROJECT);
	}
	
	FREE(URL_s->address);
	URL_s->address = remote_addr;
	
	/* If there is no topic, then we'll still attempt to load the project file and
	   its window.  The other code below should detect the non-existence of a topic and
	   either revert to a default or do some other elegant solution. */
	   
	if (topic) {
		NET_UnEscape(topic);
		URL_s->fe_data = XP_STRDUP(topic);
	} else {
		URL_s->fe_data = NULL;
	}
	
	FREEIF(topic);
	
	return MK_DATA_LOADED;
}
Пример #7
0
url_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    jsval slot;
    JSURL *url;
    JSString * str;
    char *port;
    const char *cstr, *tmp;

    if (!JSVAL_IS_INT(id))
	return JS_TRUE;

    slot = JSVAL_TO_INT(id);
    url = JS_GetInstancePrivate(cx, obj, &lm_url_class, NULL);
    if (!url) {
	url = JS_GetInstancePrivate(cx, obj, &lm_location_class, NULL);
	if (!url)
	    return JS_TRUE;
    }

    str = 0;
    cstr = 0;

    switch (slot) {
      case URL_HREF:
	str = url->href;
	break;

      case URL_PROTOCOL:
        if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_PROTOCOL_PART);
	break;

      case URL_HOST:
        if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_HOST_PART);
	break;

      case URL_HOSTNAME:
        if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_HOST_PART);
	if (cstr && (port = XP_STRCHR(cstr, ':')) != 0)
	    *port = '\0';
	break;

      case URL_PORT:
	if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_HOST_PART);
	if (cstr && (port = XP_STRCHR(cstr, ':')) != 0)
	    port++;
	else
	    port = "";
	tmp = cstr;
	cstr = JS_strdup(cx, port);
	XP_FREE((void *)tmp);
	break;

      case URL_PATHNAME:
        if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_PATH_PART);
	break;

      case URL_HASH:
        if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_HASH_PART);
	break;

      case URL_SEARCH:
	if (url->href)
	    cstr = ParseURL(JS_GetStringBytes(url->href), GET_SEARCH_PART);
	break;

      case URL_TARGET:
	if (!url->target) {
	    *vp = JSVAL_NULL;
	    return JS_TRUE;
	}
	str = url->target;
	break;

      case URL_TEXT:
	if (!url->text) {
	    *vp = JSVAL_NULL;
	    return JS_TRUE;
	}
	str = url->text;
	break;

    case URL_X:
    case URL_Y:
        return url_get_coord(cx, url, slot, vp);

      default:
	/* Don't mess with user-defined or method properties. */
          return JS_TRUE;
    }

    if (!str && cstr)
	str = JS_NewStringCopyZ(cx, cstr);
    if (cstr)
	XP_FREE((char *)cstr);
    if (!str)        
        return JS_FALSE;
    *vp = STRING_TO_JSVAL(str);
    return JS_TRUE;
}
Пример #8
0
void XFE_PrefsLdapPropDialog::cb_ok(Widget    w,
                                    XtPointer closure,
                                    XtPointer callData)
{
    XFE_PrefsLdapPropDialog *theDialog = (XFE_PrefsLdapPropDialog *)closure;
    PrefsDataLdapProp       *fep = theDialog->getData();
    Bool                     create = theDialog->getEditDir() ? False : True;
    DIR_Server              *dir = 0;

    if (create) {
        dir = (DIR_Server *)XP_ALLOC(sizeof(DIR_Server));
        DIR_InitServer(dir);
    }
    else {
        dir = theDialog->getEditDir();
        XP_FREEIF(dir->description);
        XP_FREEIF(dir->serverName);
        XP_FREEIF(dir->searchBase);
        DIR_InitServer(dir);
    }

    char   *desc = 0;
    char   *server = 0;
    char   *root = 0;
    char   *port_num_text = 0;
    char   *num_hits_text = 0;
    char    dummy;
    int     port_num = 0;
    int     num_hits = 0;
    Boolean b;
    char    temp[1024];
    char   *ptr;

    // TODO: error checking

    desc = fe_GetTextField(fep->desc_text);
    server = fe_GetTextField(fep->server_text);
    root = fe_GetTextField(fep->root_text);
    XtVaGetValues(fep->port_number_text, XmNvalue, &port_num_text, 0);
    XtVaGetValues(fep->number_of_hit_text, XmNvalue, &num_hits_text, 0);

    if (1 != sscanf(port_num_text, " %d %c", &port_num, &dummy) ||
            port_num < 0) {
        // TODO: error
    }
    if (port_num_text) XtFree(port_num_text);

    if (1 == sscanf(num_hits_text, " %d %c", &num_hits, &dummy) &&
            num_hits < 0) {
        // TODO: error
    }
    if (num_hits_text) XtFree(num_hits_text);

    if (ptr = XP_STRCHR(server, '.')) {
        XP_STRCPY(temp, ptr+1);
        if (ptr = XP_STRCHR(temp, '.')) {
            *ptr = '\0';
        }
    }
    else {
        XP_STRCPY(temp, server);
    }

    dir->description = desc ? desc : XP_STRDUP("");
    dir->serverName =  server ? server : XP_STRDUP("");
    dir->searchBase =  root ? root : XP_STRDUP("");
    // dir->htmlGateway =  NULL; // no loner use
    dir->fileName = WH_FileName(WH_TempName(xpAddrBook, temp), xpAddrBook);
    dir->port = port_num;
    dir->maxHits = num_hits;
    XtVaGetValues(fep->secure_toggle, XmNset, &b, 0);
    dir->isSecure = b;
#if 0
    XtVaGetValues(fep->save_passwd_toggle, XmNset, &b, 0);
    dir->savePassword = b;
#endif
    dir->dirType = LDAPDirectory;

    // Insert into list if this is create

    if (create) {
        XFE_PrefsPageMailNewsAddrBook *dir_page = theDialog->getAddrBookPage();
        dir_page->insertDir(dir);
    }

    // Simulate a cancel

    theDialog->cb_cancel(w, closure, callData);
}
Пример #9
0
char *
xp_TempName (XP_FileType type, const char * prefix, char* buf, char* buf2, unsigned int *count)
{
#define NS_BUFFER_SIZE	1024
    char *value = buf;
    time_t now;

    *buf = 0;
    XP_ASSERT (type != xpTemporaryNewsRC);

    if (type == xpCache || type == xpSARCache)
    {
        /* WH_TempName() must return relative pathnames for the cache files,
         so that relative paths get written into the cacheFAT database,
         making the directory relocatable.
         */
        *buf = 0;
    }
    else  if ( (type == xpURL) && prefix )
    {
        if ( XP_STRRCHR(prefix, '/') )
        {
            XP_StatStruct st;

            XP_SPRINTF (buf, "%.500s", prefix);
            if (XP_Stat (buf, &st, xpURL))
                XP_MakeDirectoryR (buf, xpURL);
            prefix = "su";
        }
    }
    else
    {
        char *tmp = FE_TempDir;
        if (!tmp || !*tmp) tmp = "/tmp";
        XP_SPRINTF (buf, "%.500s", tmp);

        if (!prefix || !*prefix)
            prefix = "tmp";
    }

    XP_ASSERT (!XP_STRCHR (prefix, '/'));
    if (*buf && buf[XP_STRLEN (buf)-1] != '/')
        XP_STRCAT (buf, "/");

    /* It's good to have the cache file names be pretty long, with a bunch of
     inputs; this makes the variant part be 15 chars long, consisting of the
     current time (in seconds) followed by a counter (to differentiate
     documents opened in the same second) followed by the current pid (to
     differentiate simultanious processes.)  This organization of the bits
     has the effect that they are ordered the same lexicographically as by
     creation time.

     If name length was an issue we could cut the character count a lot by
     printing them in base 72 [A-Za-z0-9@%-_=+.,~:].
     */
    now = time ((time_t *) 0);
    sprintf (buf2,
             "%08X%03X%04X",
             (unsigned int) now,
             (unsigned int) *count,
             (unsigned int) (getpid () & 0xFFFF));

    if (++(*count) > 4095) (*count) = 0; /* keep it 3 hex digits */

#ifdef CACHE_SUBDIRS
    if (type == xpCache || type == xpSARCache)
    {
        XP_StatStruct st;
        char *s;
        char *tmp = (type == xpCache) ? FE_CacheDir : FE_SARCacheDir;
        if (!tmp || !*tmp) tmp = "/tmp";
        sprintf (buf, "%.500s", tmp);
        if (buf [XP_STRLEN(buf)-1] != '/')
            XP_STRCAT (buf, "/");

        s = buf + XP_STRLEN (buf);

        value = s;		/* return a relative path! */

        /* The name of the subdirectory is the bottom 5 bits of the time part,
         in hex (giving a total of 32 directories.) */
        sprintf (s, "%02X", (now & 0x1F));

        if (XP_Stat (buf, &st, xpURL))		/* create the dir if necessary */
            XP_MakeDirectory (buf, type);

        s[2] = '/';
        s[3] = 0;
    }
#endif /* !CACHE_SUBDIRS */

    XP_STRNCAT (value, prefix, NS_BUFFER_SIZE - XP_STRLEN(value));
    XP_STRNCAT (value, buf2, NS_BUFFER_SIZE - XP_STRLEN(value));

    /* Tao
     */
    if (type == xpAddrBook) {
        XP_STRNCAT (value, ".nab", NS_BUFFER_SIZE - XP_STRLEN(value));
    }/* if */

    value[NS_BUFFER_SIZE - 1] = '\0'; /* just in case */

    DO_TRACE(("WH_TempName called: returning: %s", value));

    return(value);
}