Пример #1
0
PUBLIC void HTHashtable_print (HTHashtable *me)
{
    HTArray *keys = HTHashtable_keys(me);
    int i;
    HTPrint("Printing Hash Table of size %d\n", HTArray_size(keys));
    for(i = 0; i< HTArray_size(keys); i++) {
	HTPrint("Key %d %s\n",i,HTArray_data(keys)[i]);
    }
    for(i = 0; i< HTArray_size(keys); i++) {
	HT_FREE(HTArray_data(keys)[i]);
    }
    HTArray_delete(keys);
}
Пример #2
0
/*	HTDir_free
**	----------
**    	If we are sorting then do the sorting and put out the list,
**	else just append the end of the list.
*/
PUBLIC BOOL HTDir_free (HTDir * dir)
{
    if (!dir) return NO;
    if (dir->key != HT_DK_NONE) {
	HTArray *array = dir->array;
	void **data = NULL;
	HTDirNode *node;
	HTDir_headLine(dir);	
	HTArray_sort(array, (dir->key==HT_DK_CINS ? DirCaseSort : DirSort));
	node = (HTDirNode *) HTArray_firstObject(array, data);
	while (node) {
	    HTDirNode_print(dir, node);
	    HTDirNode_free(node);
	    node = (HTDirNode *) HTArray_nextObject(array, data);
	}
	dir->size = HTArray_size(array);
    	HTArray_delete(array);	
    }

    /* Put out the end of the HTML stuff */
    {
	HTStructured *target = dir->target;
	END(HTML_PRE);
	START(HTML_HR);
	START(HTML_PRE);
	if (!dir->size)
	    PUTS("Empty directory");
	else if (dir->size == 1)
	    PUTS("1 File");
	else {
	    char buffer[20];
	    sprintf(buffer, "%u files", dir->size);
	    PUTS(buffer);
	}
	END(HTML_PRE);
	END(HTML_BODY);
	END(HTML_HTML);
	FREE_TARGET;
    }

    HT_FREE(dir->fnbuf);
    HT_FREE(dir->lnbuf);
    HT_FREE(dir->base);
    HT_FREE(dir);
    return YES;
}
Пример #3
0
/*
**	Instead of just deleting we could save it to file.
*/
PRIVATE int HTNewsCache_delete (void * context)
{
    HTNewsCache * me = (HTNewsCache *) context;
    if (me) {
	if (me->cache) {
    	    void ** data;
    	    char * line = (char *) HTArray_firstObject(me->cache, data);
    	    while (line) {
		HT_FREE(line);
		line = (char *) HTArray_nextObject(me->cache, data);
    	    }
	    HTArray_delete(me->cache);
	}
	HT_FREE(me->host);
	HTTRACE(PROT_TRACE, "News Cache.. Deleted cache %p\n" _ me);
	HT_FREE(me);
	return YES;
    }
    return NO;
}
Пример #4
0
/*	HTNewsDir_free
**	--------------
**    	If we are sorting then do the sorting and put out the list,
**	else just append the end of the list.
*/
PUBLIC BOOL HTNewsDir_free (HTNewsDir * dir)
{
    if (!dir) return NO;
    if (dir->key != HT_NDK_NONE) {
    	HTArray * array = dir->array;
	HTArray * cache = NULL;
    	HTComparer * comp = NULL;

	/*
	** Find a suitable sort key for this listing. The sort function
	** depends on the type of new listing we have received.
	*/
    	if (dir->key == HT_NDK_INDEX)	           /* Sort by Message Number */
    	    comp = NDirIndexSort;
    	else if (dir->key == HT_NDK_DATE)	             /* Sort by Date */
    	    comp = NDirDateSort;
    	else if (dir->key == HT_NDK_SUBJECT)           /* Sort after Subject */
    	    comp = NDirSubjectSort;         
    	else if (dir->key == HT_NDK_FROM)		  /* Sort after From */
    	    comp = NDirFromSort;
    	else if (dir->key == HT_NDK_GROUP) {	  /* Sort as group hierarchi */
	    comp = NDirGroupSort;
        } else if (dir->key == HT_NDK_REFTHREAD) {    /* Added by MP. */
            HTNewsDir_setRefInfo (dir);
            comp = NDirRefThreadSort;
        } else {
    	    HTTRACE(STREAM_TRACE, "NewsListing. Invalid sortkey\n");
    	    return NO;
    	}

	/*
	** Now sort the array of news items that we have read with the sort
	** function defined by the sort key above.
	*/
    	HTArray_sort(array, comp);

	/*
	** If we are showing a group listing then run through the list and
	** identify group hierarchy. We have to sort the thing again in order
	** to get the new template groups included
	*/
	if (dir->key == HT_NDK_GROUP) {
	    HTNewsDir_setGroupInfo(dir);
	    HTArray_sort(array, comp);
	}
	
	/*
	** After we have sorted the listing, we can write out the result and
	** free the array.
	*/
    	{
    	    void ** data;
    	    HTNewsNode *node = (HTNewsNode *) HTArray_firstObject(array, data);
    	    while (node) {
		HTNewsNode_print(dir, node);

		/*
		** Create a special array for the cache containing the group
		** names only and no templates
		*/
		if (dir->key == HT_NDK_GROUP && !node->is_tmplate)
		    HTArray_addObject(cache, node->name);

		HTNewsNode_delete(node, (dir->cache!=NULL));
		node = (HTNewsNode *) HTArray_nextObject(array, data);
    	    }
	    HTArray_delete(array);	
	}

	/* Update the cache */
	if (dir->cache) HTNewsCache_after(dir->request, NULL, dir->cache, 0);
    }

    /* Put out the end of the HTML stuff */
    {
	HTStructured *target = dir->target;
	/* END(HTML_UL); */
        HTNewsDir_addLevelTags (dir, -1);
	START(HTML_HR);
	END(HTML_BODY);
	END(HTML_HTML);
	FREE_TARGET;
    }

    /* Clean up the dir object */
    HT_FREE(dir->name);
    HT_FREE(dir->tmplate);
    HT_FREE(dir);
    return YES;
}
Пример #5
0
/* PRIVATE						multi_match()
**
**	Check if actual filename (split in parts) fulfills
**	the requirements.
*/
PRIVATE BOOL multi_match (char ** required, int m, char ** actual, int n)
{
    int c;
    int i,j;

#ifdef VMS
    for(c=0;  c<m && c<n && !strcasecomp(required[c], actual[c]);  c++);
#else /* not VMS */
    for(c=0;  c<m && c<n && !strcmp(required[c], actual[c]);  c++);
#endif /* not VMS */

    if (!c) return NO;		/* Names differ rigth from start */

    for(i=c; i<m; i++) {
	BOOL found = NO;
	for(j=c; j<n; j++) {
#ifdef VMS
	    if (!strcasecomp(required[i], actual[j])) {
#else /* not VMS */
	    if (!strcmp(required[i], actual[j])) {
#endif /* not VMS */
		found = YES;
		break;
	    }
	}
	if (!found) return NO;
    }
    return YES;
}


/*
**	Get multi-match possibilities for a given file
**	----------------------------------------------
** On entry:
**	path	absolute path to one file in a directory,
**		may end in .multi.
** On exit:
**	returns	a list of ContentDesription structures
**		describing the mathing files.
**
*/
PRIVATE HTArray * dir_matches (char * path)
{
    static char * required[MAX_SUFF+1];
    static char * actual[MAX_SUFF+1];
    int m,n;
    char * dirname = NULL;
    char * basename = NULL;
    int baselen;
    char * multi = NULL;
    DIR * dp;
    struct dirent * dirbuf;
    HTArray * matches = NULL;
#ifdef HT_REENTRANT
    struct dirent result;				         /* For readdir_r */
#endif

    if (!path) return NULL;

    StrAllocCopy(dirname, path);
    basename = (strrchr(dirname, '/'));
    if (!basename)
	goto dir_match_failed;
    *basename++ = 0;

    multi = strrchr(basename, MULTI_SUFFIX[0]);
    if (multi && !strcasecomp(multi, MULTI_SUFFIX))
	*multi = 0;
    baselen = strlen(basename);

    m = HTSplitFilename(basename, required);

    dp = opendir(dirname);
    if (!dp) {
	HTTRACE(PROT_TRACE, "Warning..... Can't open directory %s\n" _ dirname);
	goto dir_match_failed;
    }

    matches = HTArray_new(VARIANTS);
#ifdef HAVE_READDIR_R_2
	while ((dirbuf = (struct dirent *) readdir_r(dp, &result))) {
#elif defined(HAVE_READDIR_R_3)
        while (readdir_r(dp, &result, &dirbuf) == 0) {
#else
	while ((dirbuf = readdir(dp))) {
#endif /* HAVE_READDIR_R_2 */
	if (!dirbuf->d_ino) continue;	/* Not in use */
	if (!strcmp(dirbuf->d_name,".") ||
	    !strcmp(dirbuf->d_name,"..") ||
	    !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE))
	    continue;

	/* Use of direct->namlen is only valid in BSD'ish system */
	/* Thanks to [email protected] (Chip Rosenthal) */
	/* if ((int)(dirbuf->d_namlen) >= baselen) { */
	if ((int) strlen(dirbuf->d_name) >= baselen) {
	    n = HTSplitFilename(dirbuf->d_name, actual);
	    if (multi_match(required, m, actual, n)) {
		HTContentDescription * cd;
		if ((cd = (HTContentDescription  *)
		     HT_CALLOC(1, sizeof(HTContentDescription))) == NULL)
		    HT_OUTOFMEM("dir_matches");
		if (HTBind_getFormat(dirbuf->d_name,
				     &cd->content_type,
				     &cd->content_encoding,
				     &cd->content_transfer,
				     &cd->content_language,
				     &cd->quality)) {
		    if (cd->content_type) {
			if ((cd->filename = (char *) HT_MALLOC(strlen(dirname) + 2 + strlen(dirbuf->d_name))) == NULL)
			    HT_OUTOFMEM("dir_matches");
			sprintf(cd->filename, "%s/%s", dirname, dirbuf->d_name);
			HTArray_addObject(matches, (void *) cd);
		    } else {
			HT_FREE(cd);
		    }
		} else {
		    HT_FREE(cd);
		}
	    }
	}
    }
    closedir(dp);

  dir_match_failed:
    HT_FREE(dirname);
    return matches;
}


/*
**	Get the best match for a given file
**	-----------------------------------
** On entry:
**	req->conversions  accepted content-types
**	req->encodings	  accepted content-transfer-encodings
**	req->languages	  accepted content-languages
**	path		  absolute pathname of the filename for
**			  which the match is desired.
** On exit:
**	returns	a newly allocated absolute filepath.
*/
PRIVATE char * HTGetBest (HTRequest * req, char * path)
{
    HTArray * variants = NULL;
    char * representation = NULL;

    if (!path || !*path) return NULL;

    if ((variants = dir_matches(path)) == NULL) {
	HTTRACE(PROT_TRACE, "No matches.. for \"%s\"\n" _ path);
	return NULL;
    }

#ifdef HTDEBUG
    if (PROT_TRACE) {
	void ** data;
	HTContentDescription * cd = HTArray_firstObject(variants, data);
	HTTRACE(PROT_TRACE, "Multi....... Possibilities for \"%s\"\n" _ path);
	HTTRACE(PROT_TRACE, "     QUALITY CONTENT-TYPE         LANGUAGE ENCODING  FILE\n");
	while (cd) {
	    HTTRACE(PROT_TRACE, "     %.4f  %-20.20s %-8.8s %-10.10s %s\n" _
		    cd->quality _
		    cd->content_type    ?HTAtom_name(cd->content_type)  :"-\t" _
		    cd->content_language?HTAtom_name(cd->content_language):"-" _
		    cd->content_encoding?HTAtom_name(cd->content_encoding):"-" _
		    cd->filename        ?cd->filename                    :"-");
	    cd = (HTContentDescription *) HTArray_nextObject(variants, data);
	}
    }
#endif /* HTDEBUG */

    /*
    ** Finally get the best variant which is readable
    */
    if (HTRank(req, variants)) {
	void ** data;
	HTContentDescription * cd = HTArray_firstObject(variants, data);
	while (cd) {
	    if (cd->filename) {
		if (access(cd->filename, R_OK) != -1)
		    StrAllocCopy(representation, cd->filename);
		else HTTRACE(PROT_TRACE, "Multi....... `%s\' is not readable\n" _ 
			    cd->filename);
	    }
	    HT_FREE(cd->filename);
	    HT_FREE(cd);
	    cd = (HTContentDescription *) HTArray_nextObject(variants, data);
	}
    }
    HTArray_delete(variants);
    return representation;
}



PRIVATE int welcome_value (char * name)
{
    HTList * cur = welcome_names;
    char * welcome;
    int v = 0;

    while ((welcome = (char*)HTList_nextObject(cur))) {
	v++;
	if (!strcmp(welcome,name)) return v;
    }
    return 0;
}



PRIVATE char * get_best_welcome (char * path)
{
    char * best_welcome = NULL;
    int best_value = 0;
    DIR * dp;
    struct dirent * dirbuf;
    char * last = strrchr(path, '/');

    if (!welcome_names) {
	HTAddWelcome("Welcome.html");
	HTAddWelcome("welcome.html");
#if 0
	HTAddWelcome("Index.html");
#endif
	HTAddWelcome("index.html");
    }

    if (last && last!=path) *last = 0;
    dp = opendir(path);
    if (last && last!=path) *last='/';
    if (!dp) {
	HTTRACE(PROT_TRACE, "Warning..... Can't open directory %s\n" _ path);
	return NULL;
    }
    while ((dirbuf = readdir(dp))) {
	if (!dirbuf->d_ino ||
	    !strcmp(dirbuf->d_name,".") ||
	    !strcmp(dirbuf->d_name,"..") ||
	    !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE))
	    continue;
	else {
	    int v = welcome_value(dirbuf->d_name);
	    if (v > best_value) {
		best_value = v;
		StrAllocCopy(best_welcome, dirbuf->d_name);
	    }
	}
    }
    closedir(dp);

    if (best_welcome) {
	char * welcome;
	if ((welcome = (char *) HT_MALLOC(strlen(path) + strlen(best_welcome)+2)) == NULL)
	    HT_OUTOFMEM("get_best_welcome");
	sprintf(welcome, "%s%s%s", path, last ? "" : "/", best_welcome);
	HT_FREE(best_welcome);
	HTTRACE(PROT_TRACE, "Welcome..... \"%s\"\n" _ welcome);
	return welcome;
    }
    return NULL;
}