Ejemplo n.º 1
0
/*	FLATTEN ALL ANCHORS
**	-------------------
**	Flattens the anchor web structure into an array.
**	This is useful for calculating statistics, sorting
**	the parent anchors etc.
**
**      The caller can indicate the size of the array (total
**      number of anchors if known - otherwise 0).
**
**	Return an array that must be freed by the caller or
**      NULL if no anchors.
*/
PUBLIC HTArray * HTAnchor_getArray (int growby)
{
    int cnt;
    HTArray * array = NULL;
    HTList * cur = NULL;
    if (!adult_table) return NULL;

    /* Allocate an array for the anchors */
    if (growby <= 0) growby = PARENT_HASH_SIZE;
    array = HTArray_new(growby);

    /* Traverse anchor structure */
    for (cnt=0; cnt<PARENT_HASH_SIZE; cnt++) {
	if ((cur = adult_table[cnt])) { 
	    HTParentAnchor * pres = NULL;
	    while ((pres = (HTParentAnchor *) HTList_nextObject(cur)) != NULL) {
                if (HTArray_addObject(array, pres) == NO) {
                    HTTRACE(ANCH_TRACE, "Anchor...... Can't add object %p to array %p\n" _ 
				pres _ array);
                    break;
                }
	    }
	}
    }
    return array;
}
Ejemplo n.º 2
0
/*	HTDir_addElement
**	---------------
**    	This function accepts a directory line. "data" and "size", and
**	"description" can all be NULL
**	Returns YES if OK, else NO
*/
PUBLIC BOOL HTDir_addElement (HTDir *dir, char *name, char *date, char *size,
			      HTFileMode mode)
{
    HTDirNode *node = HTDirNode_new();
    if (!dir || !name) return NO;
    if ((node->fname = (char *) HT_MALLOC(strlen(name) + 2)) == NULL)
	HT_OUTOFMEM("HTDir_addElement");
    strcpy(node->fname, name);					/* Mandatory */
    if (dir->show & HT_DS_DATE && date) StrAllocCopy(node->date, date);
    if (dir->show & HT_DS_SIZE && size) StrAllocCopy(node->size, size);
    if (dir->show & HT_DS_DES) {
#if 0

	/* FIND DESCRIPTION */

#endif
    }


    /* Set the mode of the file */
    node->mode = mode;

    /* Should we display now or later? */
    if (dir->key == HT_DK_NONE) {
	if (!dir->size++) HTDir_headLine(dir);
	HTDirNode_print(dir, node);
	HTDirNode_free(node);
    } else {
	int slen = strlen(name);
	if (slen > dir->curfw)
	    dir->curfw = slen < MaxFileW ? slen : MaxFileW;
	HTArray_addObject(dir->array, (void *) node);
    }
    return YES;
}
Ejemplo n.º 3
0
/* Helper function - added by MP. */
PUBLIC HTNewsNode * HTNewsDir_addGroupElement (HTNewsDir * dir, char * group,
					       BOOL tmplate)
{
    HTNewsNode * node = NULL;
    if (dir && group) {
	if (HTNewsDir_belongsToSet(dir, group))
	    node=HTNewsDir_addElement (dir, 0, group, NULL, 0, group, 0, NULL);

	/* If we are building a cache object then add the entry */
	if (dir->cache && !tmplate) {
	    char * name = node ? node->name : NULL;
	    if (!name) StrAllocCopy(name, group);
	    HTArray_addObject(dir->cache, name);
	}
    }
    return node;
}
Ejemplo n.º 4
0
/*	HTNewsDir_addElement
**	--------------------
**    	This function accepts a news line. Everything except dir and name can
**	can be 0 or NULL.
**	Returns new node pointer if OK, else NULL
**	Changed by MP: reference list added.
**	Note: Unlike other parameters, refNames is not copied, but assigned, so
**	it has to contain copies of message names, not the originals.
*/
PUBLIC HTNewsNode* HTNewsDir_addElement (HTNewsDir * dir, int index, 
					 char * subject, char * from,
					 time_t date, char * name,
					 int refs, HTList * refNames)
{
    if (dir && name) {
	HTNewsNode * node = HTNewsNode_new(index, subject, from,
					   date, name, refs, refNames);
	if (dir->key == HT_NDK_NONE) {
	    HTNewsNode_print(dir, node);
	    HTNewsNode_delete(node, (dir->cache!=NULL));
	} else
	    HTArray_addObject(dir->array, (void *) node);
	return node;
    }
    return NULL;
}
Ejemplo n.º 5
0
PUBLIC HTArray * HTHashtable_keys (HTHashtable *me)
{
    if(me) {
	HTArray *keys = HTArray_new(me->count);
	int i;
    
	for(i = 0; i< me->size; i++) {
	    HTList * l = (HTList *)me->table[i];
	    if (l) {
		HTList *cur = l;
		keynode *kn;
		while ((kn = (keynode *) HTList_nextObject(cur))) {
		    char * nkey = NULL;
		    StrAllocCopy(nkey,kn->key);
		    HTArray_addObject(keys,nkey);
		}
	    }
	}
	return keys;
    }
    return NULL;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
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;
}