/* --------------------------------------------------------------------------
 *
 * License
 *
 * The contents of this file are subject to the Jabber Open Source License
 * Version 1.0 (the "License").  You may not copy or use this file, in either
 * source code or executable form, except in compliance with the License.  You
 * may obtain a copy of the License at http://www.jabber.com/license/ or at
 * http://www.opensource.org/.  
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Copyrights
 * 
 * Portions created by or assigned to Jabber.com, Inc. are 
 * Copyright (c) 1999-2000 Jabber.com, Inc.  All Rights Reserved.  Contact
 * information for Jabber.com, Inc. is available at http://www.jabber.com/.
 *
 * Portions Copyright (c) 1998-1999 Jeremie Miller.
 * 
 * Acknowledgements
 * 
 * Special thanks to the Jabber Open Source Contributors for their
 * suggestions and support of Jabber.
 * 
 * --------------------------------------------------------------------------*/

#include "jud.h"

void jud_search_walk(xht h, const char *key, void *val, void *arg)
{
    xmlnode cur = (xmlnode)val;
    jpacket p = (jpacket)arg;
    xmlnode q = (xmlnode)p->aux1;
    xmlnode term;
    int flag_searched = 0;
    int flag_mismatch = 0;
    char *data;
    char *normalizeddata;

    for(term = xmlnode_get_firstchild(p->iq); term != NULL; term = xmlnode_get_nextsibling(term))
    {
        if((data = xmlnode_get_data(term)) == NULL) continue;

        flag_searched = 1;

    /*
     * by Aleksander Adamowski <olo@altkom.com.pl>:
     * Strip initial whitespace characters to workaround
     * a bug in XML parser where empty elements
     * on a line with initial whitespaces would
     * receive those whitespaces in their content
     */
    for (normalizeddata = data;
            *normalizeddata != '\0' &&
            (*normalizeddata == '\t' ||
            *normalizeddata == '\n' ||
            *normalizeddata == ' ')
            ;
        normalizeddata++)
        ;
    data = normalizeddata;

    if( (strlen(data) > 0) &&
(j_strncasecmp(data,xmlnode_get_tag_data(cur,xmlnode_get_name(term)),strlen(data)) != 0)
)
            flag_mismatch = 1;

    }

    if(flag_searched && !flag_mismatch)
        xmlnode_insert_tag_node(q,cur);
}

void jud_search(ji j, jpacket p)
{
    xmlnode q;
    xmlnode config, cur;
    char* name;

    log_debug(ZONE,"handling query from %s of %s",jid_full(p->from),xmlnode2str(p->iq));
 
    switch(jpacket_subtype(p))
    {
        case JPACKET__GET:
 
            /* create reply to the get */
            jutil_iqresult(p->x);
 
            /* create a new query */
            q = xmlnode_insert_tag(p->x, "query");
            xmlnode_put_attrib(q,"xmlns",NS_SEARCH);

            /* look for a <search/> tag - if there is one, use that for
               the instructions and fields. If there isn't, look for a
               <register/> tag - if there's one of those, get the
               searchable fields from that, substituting a sensible
               instructions text for search. If neither <search/> or
               <register/> exist, fall back to the the default
               hardcoded stuff.                                         */

            if((config = xmlnode_get_tag(j->config,"search")) != NULL || (config = xmlnode_get_tag(j->config,"register")) != NULL)
            {
                log_debug(ZONE,"config is %s",xmlnode2str(config));

                /* 'register' or 'search'? */
                name = xmlnode_get_name(config);

                for(cur = xmlnode_get_firstchild(config); cur != NULL; cur = xmlnode_get_nextsibling(cur))
                {
                    if(xmlnode_get_type(cur) != NTYPE_TAG) continue;

                    /* Make sure we give search-specific instructions if we're falling
                       back to the <register/> config                                  */
                    if(j_strcmp(xmlnode_get_name(cur), "instructions") == 0 && j_strcmp(name,"search") != 0)
                        xmlnode_insert_cdata(xmlnode_insert_tag(q,"instructions"),"Fill in a field to search",-1);
                    else
                        xmlnode_insert_tag_node(q,cur);
                }
            }
            else
            {
                log_debug(ZONE,"no config");

                xmlnode_insert_cdata(xmlnode_insert_tag(q,"instructions"),"Fill in a field to search for any matching Jabber User",-1);

                /* copy in the searchable fields */
                xmlnode_insert_tag(q,"name");
                xmlnode_insert_tag(q,"first");
                xmlnode_insert_tag(q,"last");
                xmlnode_insert_tag(q,"nick");
                xmlnode_insert_tag(q,"email");
            }
 
            break;
 
        case JPACKET__SET:

            /* create result container */
            jutil_iqresult(p->x);
            q = xmlnode_insert_tag(p->x, "query");
            xmlnode_put_attrib(q,"xmlns",NS_SEARCH);

            /* XXX-REPLACE-WITH-HASHES&INDEXES! BRUTE FORCE spin through all the entries finding the matches and copying them into the result */
            p->aux1 = (void*)q;
            xhash_walk(j->users,jud_search_walk,(void*)p);

            break;

        default:
            xmlnode_free(p->x);
            return;
    }

    /* deliver the response */
    deliver(dpacket_new(p->x),NULL);
}
