STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(SSL_METHOD *ssl_method, STACK_OF(SSL_CIPHER) **cipher_list, STACK_OF(SSL_CIPHER) **cipher_list_by_id, char *str)
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(SSL_METHOD *ssl_method,		STACK_OF(SSL_CIPHER) **cipher_list,		STACK_OF(SSL_CIPHER) **cipher_list_by_id,		char *str)	{	SSL_CIPHER *c;	char *l;	STACK_OF(SSL_CIPHER) *ret=NULL,*ok=NULL;#define CL_BUF	40	char buf[CL_BUF];	char *tmp_str=NULL;	unsigned long mask,algorithms,ma;	char *start;	int i,j,k,num=0,ch,multi;	unsigned long al;	STACK *ca_list=NULL;	int current_x,num_x;	CIPHER_CHOICE *ops=NULL;	CIPHER_ORDER *list=NULL,*head=NULL,*tail=NULL,*curr,*tail2,*curr2;	int list_num;	int type;	SSL_CIPHER c_tmp,*cp;	if (str == NULL) return(NULL);	if (strncmp(str,"DEFAULT",7) == 0)		{		i=strlen(str)+2+strlen(SSL_DEFAULT_CIPHER_LIST);		if ((tmp_str=Malloc(i)) == NULL)			{			SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);			goto err;			}		strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST);		strcat(tmp_str,":");		strcat(tmp_str,&(str[7]));		str=tmp_str;		}	if (init_ciphers) load_ciphers();	num=ssl_method->num_ciphers();	if ((ret=sk_SSL_CIPHER_new(NULL)) == NULL) goto err;	if ((ca_list=(STACK *)sk_new(cmp_by_name)) == NULL) goto err;	mask =SSL_kFZA;#ifdef NO_RSA	mask|=SSL_aRSA|SSL_kRSA;#endif#ifdef NO_DSA	mask|=SSL_aDSS;#endif#ifdef NO_DH	mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH;#endif#ifdef SSL_FORBID_ENULL	mask|=SSL_eNULL;#endif	mask|=(ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL)?SSL_DES :0;	mask|=(ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL)?SSL_3DES:0;	mask|=(ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL)?SSL_RC4 :0;	mask|=(ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL)?SSL_RC2 :0;	mask|=(ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL)?SSL_IDEA:0;	mask|=(ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL)?SSL_eFZA:0;	mask|=(ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL)?SSL_MD5 :0;	mask|=(ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL)?SSL_SHA1:0;	if ((list=(CIPHER_ORDER *)Malloc(sizeof(CIPHER_ORDER)*num)) == NULL)		goto err;	/* Get the initial list of ciphers */	list_num=0;	for (i=0; i<num; i++)		{		c=ssl_method->get_cipher((unsigned int)i);		/* drop those that use any of that is not available */		if ((c != NULL) && c->valid && !(c->algorithms & mask))			{			list[list_num].cipher=c;			list[list_num].next=NULL;			list[list_num].prev=NULL;			list[list_num].active=0;			list_num++;			if (!sk_push(ca_list,(char *)c)) goto err;			}		}		for (i=1; i<list_num-1; i++)		{		list[i].prev= &(list[i-1]);		list[i].next= &(list[i+1]);		}	if (list_num > 0)		{		head= &(list[0]);		head->prev=NULL;		head->next= &(list[1]);		tail= &(list[list_num-1]);		tail->prev= &(list[list_num-2]);		tail->next=NULL;		}	/* special case */	cipher_aliases[0].algorithms &= ~mask;	/* get the aliases */	k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER);	for (j=0; j<k; j++)		{		al=cipher_aliases[j].algorithms;		/* Drop those that are not relevent */		if ((al & mask) == al) continue;		if (!sk_push(ca_list,(char *)&(cipher_aliases[j]))) goto err;		}	/* ca_list now holds a 'stack' of SSL_CIPHERS, some real, some	 * 'aliases' */	/* how many parameters are there? */	num=1;	for (l=str; *l; l++)		if (ITEM_SEP(*l))			num++;	ops=(CIPHER_CHOICE *)Malloc(sizeof(CIPHER_CHOICE)*num);	if (ops == NULL) goto err;	memset(ops,0,sizeof(CIPHER_CHOICE)*num);	/* we now parse the input string and create our operations */	l=str;	i=0;	current_x=0;	for (;;)		{		ch= *l;		if (ch == '\0') break;		if (ch == '-')			{ j=CIPHER_DEL; l++; }		else if (ch == '+')			{ j=CIPHER_ORD; l++; }		else if (ch == '!')			{ j=CIPHER_KILL; l++; }		else				{ j=CIPHER_ADD; }		if (ITEM_SEP(ch))			{			l++;			continue;			}		ops[current_x].type=j;		ops[current_x].algorithms=0;		ops[current_x].mask=0;		start=l;		for (;;)			{			ch= *l;			i=0;#ifndef CHARSET_EBCDIC			while (	((ch >= 'A') && (ch <= 'Z')) ||				((ch >= '0') && (ch <= '9')) ||				((ch >= 'a') && (ch <= 'z')) ||				 (ch == '-'))#else			while (	isalnum(ch) || (ch == '-'))#endif				 {				 buf[i]=ch;				 ch= *(++l);				 i++;				 if (i >= (CL_BUF-2)) break;				 }			buf[i]='\0';			/* check for multi-part specification */			if (ch == '+')				{				multi=1;				l++;				}			else				multi=0;			c_tmp.name=buf;			j=sk_find(ca_list,(char *)&c_tmp);			if (j < 0)				goto end_loop;			cp=(SSL_CIPHER *)sk_value(ca_list,j);			ops[current_x].algorithms|=cp->algorithms;			/* We add the SSL_SSL_MASK so we can match the			 * SSLv2 and SSLv3 versions of RC4-MD5 */			ops[current_x].mask|=cp->mask;			if (!multi) break;			}		current_x++;		if (ch == '\0') break;end_loop:		/* Make sure we scan until the next valid start point */		while ((*l != '\0') && ITEM_SEP(*l))			l++;		}	num_x=current_x;	current_x=0;	/* We will now process the list of ciphers, once for each category, to	 * decide what we should do with it. */	for (j=0; j<num_x; j++)		{		algorithms=ops[j].algorithms;		type=ops[j].type;		mask=ops[j].mask;		curr=head;		curr2=head;		tail2=tail;		for (;;)			{			if ((curr == NULL) || (curr == tail2)) break;			curr=curr2;			curr2=curr->next;			cp=curr->cipher;			ma=mask & cp->algorithms;			if ((ma == 0) || ((ma & algorithms) != ma))				{				/* does not apply */				continue;				}			/* add the cipher if it has not been added yet. */			if (type == CIPHER_ADD)				{				if (!curr->active)					{					ll_append_tail(&head,curr,&tail);					curr->active=1;					}				}			/* Move the added cipher to this location */			else if (type == CIPHER_ORD)				{				if (curr->active)					{					ll_append_tail(&head,curr,&tail);					}				}			else if	(type == CIPHER_DEL)				curr->active=0;			if (type == CIPHER_KILL)				{				if (head == curr)					head=curr->next;				else					curr->prev->next=curr->next;				if (tail == curr)					tail=curr->prev;				curr->active=0;				if (curr->next != NULL)					curr->next->prev=curr->prev;				if (curr->prev != NULL)					curr->prev->next=curr->next;				curr->next=NULL;				curr->prev=NULL;				}			}		}	for (curr=head; curr != NULL; curr=curr->next)		{		if (curr->active)			{			sk_SSL_CIPHER_push(ret,curr->cipher);#ifdef CIPHER_DEBUG			printf("<%s>\n",curr->cipher->name);#endif			}		}	if (cipher_list != NULL)		{		if (*cipher_list != NULL)			sk_SSL_CIPHER_free(*cipher_list);		*cipher_list=ret;		}	if (cipher_list_by_id != NULL)		{		if (*cipher_list_by_id != NULL)			sk_SSL_CIPHER_free(*cipher_list_by_id);		*cipher_list_by_id=sk_SSL_CIPHER_dup(ret);		}	if (	(cipher_list_by_id == NULL) ||		(*cipher_list_by_id == NULL) ||		(cipher_list == NULL) ||		(*cipher_list == NULL))		goto err;	sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);	ok=ret;	ret=NULL;err:	if (tmp_str) Free(tmp_str);	if (ops != NULL) Free(ops);	if (ret != NULL) sk_SSL_CIPHER_free(ret);	if (ca_list != NULL) sk_free(ca_list);	if (list != NULL) Free(list);	return(ok);	}