/** BEGIN COPYRIGHT BLOCK * This Program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; version 2 of the License. * * This Program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA. * * In addition, as a special exception, Red Hat, Inc. gives You the additional * right to link the code of this Program with code not covered under the GNU * General Public License ("Non-GPL Code") and to distribute linked combinations * including the two, subject to the limitations in this paragraph. Non-GPL Code * permitted under this exception must only link to the code of this Program * through those well defined interfaces identified in the file named EXCEPTION * found in the source code files (the "Approved Interfaces"). The files of * Non-GPL Code may instantiate templates or use macros or inline functions from * the Approved Interfaces without causing the resulting work to be covered by * the GNU General Public License. Only Red Hat, Inc. may make changes or * additions to the list of Approved Interfaces. You must obey the GNU General * Public License in all respects for all of the Program code and other code used * in conjunction with the Program except the Non-GPL Code covered by this * exception. If you modify this file, you may extend this exception to your * version of the file, but you are not obligated to do so. If you do not wish to * provide this exception without modification, you must delete this exception * statement from your version and license this file solely under the GPL without * exception. * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H # include #endif /** * IM Presence plug-in */ #include #include #include #include "portable.h" #include "nspr.h" #include "slapi-plugin.h" #include "slapi-private.h" #include "vattr_spi.h" #include "plhash.h" #include "ldif.h" #include "http_client.h" /* get file mode flags for unix */ #ifndef _WIN32 #include #endif /*** from proto-slap.h ***/ int slapd_log_error_proc( char *subsystem, char *fmt, ... ); /*** from ldaplog.h ***/ /* edited ldaplog.h for LDAPDebug()*/ #ifndef _LDAPLOG_H #define _LDAPLOG_H #ifdef __cplusplus extern "C" { #endif #define LDAP_DEBUG_TRACE 0x00001 /* 1 */ #define LDAP_DEBUG_ANY 0x04000 /* 16384 */ #define LDAP_DEBUG_PLUGIN 0x10000 /* 65536 */ /* debugging stuff */ # ifdef _WIN32 extern int *module_ldap_debug; # define LDAPDebugLevelIsSet( level ) ( *module_ldap_debug & level ) # else /* _WIN32 */ extern int slapd_ldap_debug; # define LDAPDebugLevelIsSet( level ) ( slapd_ldap_debug & level ) # endif /* Win32 */ #define LDAPDebug( level, fmt, arg1, arg2, arg3 ) \ { \ if ( LDAPDebugLevelIsSet( level )) { \ slapd_log_error_proc( NULL, fmt, arg1, arg2, arg3 ); \ } \ } #ifdef __cplusplus } #endif #endif /* _LDAP_H */ #define PRESENCE_PLUGIN_SUBSYSTEM "presence-plugin" #define PRESENCE_PLUGIN_VERSION 0x00050050 /** * this may become unnecessary when we are able to get * the plug-in DN dynamically (pete?) */ #define PRESENCE_DN "cn=Presence,cn=plugins,cn=config" /* temporary */ #define PRESENCE_SUCCESS 0 #define PRESENCE_FAILURE -1 /** * Presence vendor specific config parameters */ #define NS_IM_ID "nsIM-ID" #define NS_IM_URL_TEXT "nsIM-URLText" #define NS_IM_URL_GRAPHIC "nsIM-URLGraphic" #define NS_IM_ON_VALUE_MAP_TEXT "nsIM-OnValueMapText" #define NS_IM_OFF_VALUE_MAP_TEXT "nsIM-OffValueMapText" #define NS_IM_ON_VALUE_MAP_GRAPHIC "nsIM-OnValueMapGraphic" #define NS_IM_OFF_VALUE_MAP_GRAPHIC "nsIM-OffValueMapGraphic" #define NS_IM_DISABLED_VALUE_MAP_GRAPHIC "nsIM-disabledValueMapGraphic" #define NS_IM_REQUEST_METHOD "nsIM-RequestMethod" #define NS_IM_URL_TEXT_RETURN_TYPE "nsIM-URLTextReturnType" #define NS_IM_URL_GRAPHIC_RETURN_TYPE "nsIM-URLGraphicReturnType" #define NS_IM_STATUS_TEXT "nsIM-StatusText" #define NS_IM_STATUS_GRAPHIC "nsIM-StatusGraphic" #define PRESENCE_STRING 1 #define PRESENCE_BINARY 2 #define PRESENCE_TEXT_RETURN_TYPE "TEXT" #define PRESENCE_BINARY_RETURN_TYPE "BINARY" #define PRESENCE_REQUEST_METHOD_GET "GET" #define PRESENCE_REQUEST_METHOD_REDIRECT "REDIRECT" #define PRESENCE_RETURNED_ON_TEXT "ONLINE" #define PRESENCE_RETURNED_OFF_TEXT "OFFLINE" #define PRESENCE_RETURNED_ERROR_TEXT "ERROR" static Slapi_PluginDesc pdesc = { "IM Presence", VENDOR, DS_PACKAGE_VERSION, "presence plugin" }; /** * struct used to pass the argument to PL_Enumerator Callback */ struct _vattrtypes { Slapi_Entry *entry; vattr_type_list_context *context; }; /** * This structure holds the mapping between the virtual attributes and * the IM IDs. This information is used to find out whether this plugin * should service the attributes it was asked to. Also, it stores the * syntax of the attribute. 1 is String and 2 is binary. */ struct _vattrmap { char *imID; int syntax; }; typedef struct _vattrmap _Vmap; /** * struct to store the config values for each presence vendor */ struct _defs { char *textURL; char *graphicURL; char *onTextMap; char *offTextMap; Slapi_Attr *onGraphicMap; Slapi_Attr *offGraphicMap; Slapi_Attr *disabledGraphicMap; char *requestMethod; char *textReturnType; char *graphicReturnType; }; typedef struct _defs _ConfigEntry; static vattr_sp_handle *_VattrHandle = NULL; static void *_PluginID = NULL; static char *_PluginDN = NULL; static PLHashTable *_IdVattrMapTable = NULL; static PLHashTable *_IdConfigMapTable = NULL; static void **_HttpAPI = NULL; /** * * Presence plug-in management functions * */ int presence_init(Slapi_PBlock *pb); int presence_start(Slapi_PBlock *pb); int presence_close(Slapi_PBlock *pb); /** * * Vattr operation callbacks functions * */ static int presence_vattr_get(vattr_sp_handle *handle, vattr_context *c, Slapi_Entry *e, char *type, Slapi_ValueSet** results,int *type_name_disposition, char** actual_type_name, int flags, int *free_flags, void *hint); static int presence_vattr_compare(vattr_sp_handle *handle, vattr_context *c, Slapi_Entry *e, char *type, Slapi_Value *test_this, int* result, int flags, void *hint); static int presence_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,vattr_type_list_context *type_context,int flags); /** * * Local operation functions * */ static int loadPluginConfig(); static int parseConfigEntry(Slapi_Entry *e); static int imIDExists(Slapi_Entry *e, char *type, char **value, _Vmap **map, _ConfigEntry **entry); static int makeHttpRequest(char *id, _Vmap *map, _ConfigEntry *info, char **buf, int *size); static char * replaceIdWithValue(char *str, char *id, char *value); static int setIMStatus(char *id, _Vmap *map, _ConfigEntry *info, char *returnedBUF, int size, Slapi_ValueSet **results); static int setTypes(PLHashEntry *he, PRIntn i, void *arg); static void deleteMapTables(); static PRIntn destroyHashEntry(PLHashEntry *he, PRIntn index, void *arg); static void logGraphicAttributeValue( Slapi_Attr *attr, const char *attrname ); static void toLowerCase(char* str); /** * utility function */ void printMapTable(); PRIntn printIdVattrMapTable(PLHashEntry *he, PRIntn i, void *arg); PRIntn printIdConfigMapTable(PLHashEntry *he, PRIntn i, void *arg); /** * set the debug level */ #ifdef _WIN32 int *module_ldap_debug = 0; void plugin_init_debug_level(int *level_ptr) { module_ldap_debug = level_ptr; } #endif /** * * Get the presence plug-in version * */ int presence_version() { return PRESENCE_PLUGIN_VERSION; } /** * Plugin identity mgmt */ void setPluginID(void * pluginID) { _PluginID=pluginID; } void * getPluginID() { return _PluginID; } void setPluginDN(char *pluginDN) { _PluginDN = pluginDN; } char * getPluginDN() { return _PluginDN; } /* presence_init ------------- adds our callbacks to the list */ int presence_init( Slapi_PBlock *pb ) { int status = PRESENCE_SUCCESS; char * plugin_identity=NULL; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> presence_init -- BEGIN\n",0,0,0); /** * Store the plugin identity for later use. * Used for internal operations */ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity); PR_ASSERT (plugin_identity); setPluginID(plugin_identity); if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *) presence_start ) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *) presence_close ) != 0 || slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) != 0 ) { slapi_log_error( SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "presence_init: failed to register plugin\n" ); status = PRESENCE_FAILURE; } LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- presence_init -- END\n",0,0,0); return status; } /* presence_start -------------- This function registers the computed attribute evaluator and loads the configuration parameters in the local cache. It is called after presence_init. */ int presence_start( Slapi_PBlock *pb ) { char * plugindn = NULL; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> presence_start -- begin\n",0,0,0); if(slapi_apib_get_interface(HTTP_v1_0_GUID, &_HttpAPI)) { /** * error cannot proceeed */ return PRESENCE_FAILURE; } /** * register our vattr callbacks */ if (slapi_vattrspi_register((vattr_sp_handle **)&_VattrHandle, presence_vattr_get, presence_vattr_compare, presence_vattr_types) != 0) { slapi_log_error( SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "presence_start: cannot register as service provider\n" ); return PRESENCE_FAILURE; } /** * Get the plug-in target dn from the system * and store it for future use. This should avoid * hardcoding of DN's in the code. */ slapi_pblock_get(pb, SLAPI_TARGET_DN, &plugindn); if (plugindn == NULL || strlen(plugindn) == 0) { /** * This is not required as the above statement * should work and give you a valid DN for this * plugin. ??? remove it later */ plugindn = PRESENCE_DN; } setPluginDN(plugindn); /** * Load the config info for our plug-in in memory * In the 6.0 release this information will be stored * statically and if any change is done to this info a server * restart is necessary :-(. Probably if time permits then * state change plug-in would be used to notify the state * change. We also register the virtual attributes we are * interested in here. */ if (loadPluginConfig() != PRESENCE_SUCCESS) { slapi_log_error( SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "presence_start: unable to load plug-in configuration\n" ); return PRESENCE_FAILURE; } LDAPDebug( LDAP_DEBUG_PLUGIN, "presence: ready for service\n",0,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- presence_start -- end\n",0,0,0); return PRESENCE_SUCCESS; } /* presence_close -------------- closes down the cache */ int presence_close( Slapi_PBlock *pb ) { LDAPDebug( LDAP_DEBUG_PLUGIN, "--> presence_close\n",0,0,0); deleteMapTables(); LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- presence_close\n",0,0,0); return PRESENCE_SUCCESS; } static int presence_vattr_get(vattr_sp_handle *handle, vattr_context *c, Slapi_Entry *e, char *type, Slapi_ValueSet** results, int *type_name_disposition, char** actual_type_name, int flags, int *free_flags, void *hint) { int status = PRESENCE_SUCCESS; char *id = NULL; char *returnedBUF = NULL; int size = 0; _Vmap *map = NULL; _ConfigEntry *info = NULL; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> presence_vattr_get \n",0,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Type=[%s] \n",type,0,0); if (imIDExists(e, type, &id, &map, &info) != PRESENCE_SUCCESS) { /** * we didn't find any valid matching nsimid in this * entry so since we cannot process a request without * a valid nsimid we just return. */ status = PRESENCE_FAILURE; goto cleanup; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> ID=[%s] \n",id,0,0); /** * Now since we got a valid id we do a quick schema check * if schema checking is on to make sure that there is no * schema violation ? */ /* do_schema_check() */ /** * At this stage we have a valid attribute and we have to * get its value from the IM Server. so make an Http request * depending on whether it is a request for Text or Graphic */ status = makeHttpRequest(id, map, info, &returnedBUF, &size); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> size=[%d] \n",size,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> buffer=[%s]\n",(returnedBUF) ? returnedBUF : "NULL",0,0); if(status == PRESENCE_SUCCESS) { status = setIMStatus(id, map, info, returnedBUF, size, results); } else { /** * Report all HTTP failures as a single predefined value of the * attribute */ Slapi_Value *value = slapi_value_new_string(PRESENCE_RETURNED_ERROR_TEXT); if (!*results) { *results = slapi_valueset_new(); } slapi_valueset_add_value(*results, value); slapi_value_free(&value); /* slapi_valueset_add_value copies value */ /** * It's a success only in the sense that we are returning a value */ status = PRESENCE_SUCCESS; } if(status == PRESENCE_SUCCESS) { *free_flags = SLAPI_VIRTUALATTRS_RETURNED_COPIES; *actual_type_name = slapi_ch_strdup(type); *type_name_disposition = SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_EXACTLY_OR_ALIAS; } cleanup: LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Processed ID=[%s] \n",id,0,0); if (id != NULL ) { slapi_ch_free((void **)&id); } if (returnedBUF != NULL ) { PR_Free(returnedBUF); } LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- presence_vattr_get \n",0,0,0); return status; } static int presence_vattr_compare(vattr_sp_handle *handle, vattr_context *c, Slapi_Entry *e, char *type, Slapi_Value *test_this, int* result, int flags, void *hint) { int status = PRESENCE_SUCCESS; /** * not yet implemented ??? */ LDAPDebug( LDAP_DEBUG_PLUGIN, "--> presence_vattr_compare \n",0,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- presence_vattr_compare \n",0,0,0); return status; } static int presence_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,vattr_type_list_context *type_context,int flags) { int status = PRESENCE_SUCCESS; struct _vattrtypes args; args.entry = e; args.context = type_context; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> presence_vattr_types\n",0,0,0); PL_HashTableEnumerateEntries(_IdVattrMapTable, setTypes, &args); LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- presence_vattr_types\n",0,0,0); return status; } static int loadPluginConfig() { int status = PRESENCE_SUCCESS; int result; int i; Slapi_PBlock *search_pb; Slapi_Entry **entries = NULL; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> loadPluginConfig\n",0,0,0); search_pb = slapi_pblock_new(); slapi_search_internal_set_pb(search_pb, PRESENCE_DN, LDAP_SCOPE_ONELEVEL, "objectclass=*", NULL, 0, NULL, NULL, getPluginID(), 0); slapi_search_internal_pb(search_pb); slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result); if (status != PRESENCE_SUCCESS) { slapi_log_error(SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "Error getting level1 presence configurations<%s>\n", getPluginDN()); status = PRESENCE_FAILURE; goto cleanup; } slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); if (NULL == entries || entries[0] == NULL) { slapi_log_error(SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "No entries found for <%s>\n", getPluginDN()); status = PRESENCE_FAILURE; goto cleanup; } _IdVattrMapTable = PL_NewHashTable( 0, PL_HashString, PL_CompareStrings, PL_CompareValues, NULL, NULL ); _IdConfigMapTable = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareValues, NULL, NULL ); LDAPDebug( LDAP_DEBUG_PLUGIN, "--> parseConfigEntry \n",0,0,0); for (i = 0; (entries[i] != NULL); i++) { status = parseConfigEntry(entries[i]); if (status != PRESENCE_SUCCESS) { deleteMapTables(); goto cleanup; } } LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- parseConfigEntry \n",0,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- loadPluginConfig\n",0,0,0); cleanup: slapi_free_search_results_internal(search_pb); slapi_pblock_destroy(search_pb); return status; } static int parseConfigEntry(Slapi_Entry *e) { char *key = NULL; char *value = NULL; _ConfigEntry *entry = NULL; _Vmap *map = NULL; Slapi_Attr *attr = NULL; key = slapi_entry_attr_get_charptr(e, NS_IM_ID); if (!key) { /** * IM Id not defined in the config, unfortunately * cannot do anything without it so better not to * load the plug-in. */ return PRESENCE_FAILURE; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> key [%s] \n",key,0,0); /** * Now create the config entry which will hold all the * attributes of a presence vendor */ entry = (_ConfigEntry*) slapi_ch_calloc(1, sizeof(_ConfigEntry)); /** * Next 2 are the virtual attributes for which this plug-in * is responsible. Register them with the vattr system so * that the system can call us whenever their * values are requested. Also update these entries in the * map table for later access. */ value = slapi_entry_attr_get_charptr(e, NS_IM_STATUS_TEXT); if (value) { slapi_vattrspi_regattr(_VattrHandle, value, "", NULL); map = (_Vmap*) slapi_ch_calloc(1, sizeof(_Vmap)); map->imID = key; map->syntax = PRESENCE_STRING; toLowerCase(value); PL_HashTableAdd(_IdVattrMapTable, value, map); } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMStatusText [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_STATUS_GRAPHIC); if (value) { slapi_vattrspi_regattr(_VattrHandle, value, "", NULL); map = (_Vmap*) slapi_ch_calloc(1, sizeof(_Vmap)); map->imID = key; map->syntax = PRESENCE_BINARY; toLowerCase(value); PL_HashTableAdd(_IdVattrMapTable, value, map); } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMStatusGraphic [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_URL_TEXT); if (value) { entry->textURL = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMURLText [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_URL_GRAPHIC); if (value) { entry->graphicURL = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMStatusGraphic [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_ON_VALUE_MAP_TEXT); if (value) { entry->onTextMap = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMOnValueMapText [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_OFF_VALUE_MAP_TEXT); if (value) { entry->offTextMap = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMOffValueMapText [%s] \n",value,0,0); /** * Next 3 are binary syntax types so needs special handling */ slapi_entry_attr_find(e, NS_IM_ON_VALUE_MAP_GRAPHIC, &attr); if (attr) { entry->onGraphicMap = slapi_attr_dup(attr); logGraphicAttributeValue(attr,NS_IM_ON_VALUE_MAP_GRAPHIC); } slapi_entry_attr_find(e, NS_IM_OFF_VALUE_MAP_GRAPHIC, &attr); if (attr) { entry->offGraphicMap = slapi_attr_dup(attr); logGraphicAttributeValue(attr,NS_IM_OFF_VALUE_MAP_GRAPHIC); } slapi_entry_attr_find(e, NS_IM_DISABLED_VALUE_MAP_GRAPHIC, &attr); if (attr) { entry->disabledGraphicMap = slapi_attr_dup(attr); logGraphicAttributeValue(attr,NS_IM_DISABLED_VALUE_MAP_GRAPHIC); } value = slapi_entry_attr_get_charptr(e, NS_IM_REQUEST_METHOD); if (value) { entry->requestMethod = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMRequestMethod [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_URL_TEXT_RETURN_TYPE); if (value) { entry->textReturnType = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMURLTextReturnType [%s] \n",value,0,0); value = slapi_entry_attr_get_charptr(e, NS_IM_URL_GRAPHIC_RETURN_TYPE); if (value) { entry->graphicReturnType = value; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> nsIMURLGraphicReturnType [%s] \n",value,0,0); /** * Finally add the entry to the map table */ PL_HashTableAdd(_IdConfigMapTable, key, entry); return PRESENCE_SUCCESS; } /** * this function goes thru the valid stored ids * and return the correct one for which we have to * do further processing */ static int imIDExists(Slapi_Entry *e, char *type, char **value, _Vmap **map, _ConfigEntry **entry) { int status = PRESENCE_SUCCESS; char *tValue = NULL; _ConfigEntry *tEntry = NULL; _Vmap *tMap = NULL; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> imIDExists \n",0,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Type [%s] \n",type,0,0); /** * The public function PL_HashTableLookup modifies the * the table while reading. so using this private function * which just does a lookup and doesn't modifies the * hashtable */ toLowerCase(type); tMap = PL_HashTableLookupConst(_IdVattrMapTable, type); if (!tMap) { /** * this should not happen but no harm we just return */ status = PRESENCE_FAILURE; slapi_log_error(SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "No hashtable for vattr types\n"); goto bail; } /** * We found a matching id in the map table * now see if that id exists in the Slapi_Entry */ tValue = slapi_entry_attr_get_charptr(e, tMap->imID); if (!tValue) { /** * we don't do anything here but just return */ status = PRESENCE_FAILURE; goto bail; } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Value [%s] \n",tValue,0,0); tEntry = PL_HashTableLookupConst(_IdConfigMapTable, tMap->imID); *value = tValue; *entry = tEntry; *map = tMap; LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- imIDExists \n",0,0,0); bail: return status; } static int makeHttpRequest(char *id, _Vmap *map, _ConfigEntry *info, char **BUF, int *size) { int status = PRESENCE_SUCCESS; char *buf = NULL; char *url = NULL; char *urltosend = NULL; int bytesRead; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> makeHttpRequest:: \n",0,0,0); if (map->syntax == PRESENCE_STRING) { url = info->textURL; } else { url = info->graphicURL; } if (url == NULL) { status = PRESENCE_FAILURE; goto bail; } urltosend = replaceIdWithValue(url, map->imID, id); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> URL [%s] \n",urltosend,0,0); /** * make an actual HTTP call now */ LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> RequestMethod [%s] \n", info->requestMethod,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Syntax [%d] \n", map->syntax,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> TextReturnType [%s] \n", info->textReturnType,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> GraphicReturnType [%s] \n", info->graphicReturnType,0,0); if (!strcasecmp(info->requestMethod, PRESENCE_REQUEST_METHOD_GET)) { if (map->syntax == PRESENCE_STRING) { if (!strcasecmp(info->textReturnType, PRESENCE_TEXT_RETURN_TYPE)) { status = http_get_text(_HttpAPI, urltosend, &buf, &bytesRead); } else { status = http_get_binary(_HttpAPI, urltosend, &buf, &bytesRead); } } else { if (!strcasecmp(info->graphicReturnType, PRESENCE_TEXT_RETURN_TYPE)) { status = http_get_text(_HttpAPI, urltosend, &buf, &bytesRead); } else { status = http_get_binary(_HttpAPI, urltosend, &buf, &bytesRead); } } } else if (!strcasecmp(info->requestMethod, PRESENCE_REQUEST_METHOD_REDIRECT)) { status = http_get_redirected_uri(_HttpAPI, urltosend, &buf, &bytesRead); } else { /** * error : unknown method * probably we should check at the time of loading * of the plugin itself that the config values are * properly checked and throw warning/errors in case * of any invalid entry */ slapi_log_error(SLAPI_LOG_FATAL, PRESENCE_PLUGIN_SUBSYSTEM, "Unknown request type <%s>\n", info->requestMethod); status = PRESENCE_FAILURE; goto bail; } if (buf && status == PRESENCE_SUCCESS) { *BUF = buf; *size = bytesRead; } bail: LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- makeHttpRequest:: <%d>\n",status,0,0); slapi_ch_free((void**)&urltosend); return status; } /** * This function replaces the occurrence of $ns[]imid with its * actual value * e.g. * URL : http://opi.yahoo.com/online?u=$nsyimid * after replacing * newURL : http://opi.yahoo.com/online?u=srajam */ static char * replaceIdWithValue(char *str, char *id, char *value) { int i=0; int k=0; char *newstr = NULL; char c; if (!str || !id || !value) { return NULL; } /* extra space for userids */ newstr = (char *)slapi_ch_malloc(strlen(str) + strlen(value)); while ((c=str[i]) != '\0') { if (c == '$') { int j = 0; i++; /*skip one char */ /** * we found the begining of the string to be * substituted. Now skip the chars we want to replace */ while (str[i] != '\0' && id[j] != '\0' && (toupper(str[i]) == toupper(id[j]))) { i++; j++; } j=0; while (value[j] != '\0') { newstr[k++] = value[j++]; } } else { newstr[k++]=c; i++; } } newstr[k] = '\0'; return newstr; } static int setIMStatus(char *id, _Vmap *map, _ConfigEntry *info, char *returnedBUF, int size, Slapi_ValueSet **results) { int status = PRESENCE_SUCCESS; char *ontxtmap = NULL; char *offtxtmap = NULL; Slapi_Value *value = NULL; Slapi_Value *value1 = NULL; Slapi_Value *value2 = NULL; struct berval bval; Slapi_Attr *attr = NULL; const struct berval *tmp = NULL; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> setIMStatus \n", 0,0,0); /** * we got some data back so lets try to map it to * the existing set of on/off data * * first we need to take a look at the * returned type and depending upon that parse * the data */ if (map->syntax == PRESENCE_STRING) { /** * we had send a request for text * but chances are we might end up * getting an image back. So we need * to compare it to existing set of * images that we have in store ??? */ if (!strcasecmp(info->textReturnType, PRESENCE_TEXT_RETURN_TYPE)) { /* return value is in text format */ ontxtmap = replaceIdWithValue(info->onTextMap, map->imID, id); offtxtmap = replaceIdWithValue(info->offTextMap, map->imID, id); if (!strcasecmp(ontxtmap, returnedBUF)) { /** * set the on value */ value = slapi_value_new_string(PRESENCE_RETURNED_ON_TEXT); } else if (!strcasecmp(offtxtmap, returnedBUF)) { /** * set the off value */ value = slapi_value_new_string(PRESENCE_RETURNED_OFF_TEXT); } else { value = slapi_value_new_string(PRESENCE_RETURNED_ERROR_TEXT); } } else if (!strcasecmp(info->textReturnType, PRESENCE_BINARY_RETURN_TYPE)) { /** * call binary compare method */ bval.bv_len = size; bval.bv_val = returnedBUF; value1 = slapi_value_new_berval(&bval); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> returned size [%d] \n", bval.bv_len,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> returned value [%s] \n", bval.bv_val,0,0); attr = info->onGraphicMap; if (attr) { slapi_attr_first_value(attr, &value2); tmp = slapi_value_get_berval(value2); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Stored size [%d] \n", tmp->bv_len,0,0); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> Stored value [%s] \n", tmp->bv_val,0,0); if (!slapi_value_compare(attr, value1, value2)) { value = slapi_value_new_string(PRESENCE_RETURNED_ON_TEXT); } } if (!value) { attr = info->offGraphicMap; if (attr) { slapi_attr_first_value(attr, &value2); if (!slapi_value_compare(attr, value1, value2)) { value = slapi_value_new_string(PRESENCE_RETURNED_OFF_TEXT); } } } if (!value) { attr = info->disabledGraphicMap; if (attr) { slapi_attr_first_value(attr, &value2); if (!slapi_value_compare(attr, value1, value2)) { value = slapi_value_new_string(PRESENCE_RETURNED_OFF_TEXT); } } } if (!value) { /* some error */ value = slapi_value_new_string(PRESENCE_RETURNED_ERROR_TEXT); } } else { /** * set the error condition */ value = slapi_value_new_string(PRESENCE_RETURNED_ERROR_TEXT); } LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> value [%s] \n", returnedBUF,0,0); } else { /** * we had send a request for image * so whatever we get back we just * return instead of analyzing it */ if (!strcasecmp(info->graphicReturnType, PRESENCE_TEXT_RETURN_TYPE)) { LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> value [%s] \n", returnedBUF,0,0); if (!strcasecmp(info->requestMethod, PRESENCE_REQUEST_METHOD_REDIRECT)) { /** * a redirect case in which we should probably have a * gif in store so return that value * * for now */ ontxtmap = replaceIdWithValue(info->onTextMap, map->imID, id); offtxtmap = replaceIdWithValue(info->offTextMap, map->imID, id); if (!strcasecmp(ontxtmap, returnedBUF)) { /** * set the on value */ attr = info->onGraphicMap; } else if (!strcasecmp(offtxtmap, returnedBUF)) { /** * set the off value */ attr = info->offGraphicMap; } else { attr = info->disabledGraphicMap; } if (attr) { slapi_attr_first_value(attr, &value); } } else { /** * for now just set the returned value * should not happen in our case * ERROR */ } } else { LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> value [%s] \n", returnedBUF,0,0); bval.bv_len = size; bval.bv_val = returnedBUF; value = slapi_value_new_berval(&bval); } } if (!*results) { *results = slapi_valueset_new(); } slapi_valueset_add_value(*results, value); if (ontxtmap) { slapi_ch_free((void **)&ontxtmap); } if (offtxtmap) { slapi_ch_free((void **)&offtxtmap); } if (value && map->syntax == PRESENCE_STRING) { slapi_value_free(&value); } LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- setIMStatus \n", 0,0,0); return status; } static int setTypes(PLHashEntry *he, PRIntn i, void *arg) { int status; int props = SLAPI_ATTR_FLAG_OPATTR; Slapi_ValueSet *results = NULL; int type_name_disposition = 0; char *actual_type_name = 0; int free_flags = 0; struct _vattrtypes *args = arg; char *type = (char *)he->key; _Vmap *map = (_Vmap *)he->value; char *id = map->imID; LDAPDebug( LDAP_DEBUG_PLUGIN, "--> setTypes \n", 0,0,0); status = slapi_vattr_values_get_sp(NULL, args->entry, id, &results, &type_name_disposition, &actual_type_name, 0, &free_flags); if(status == PRESENCE_SUCCESS) { /* entry contains this attr */ vattr_type_thang thang = {0}; thang.type_name = type; thang.type_flags = props; slapi_vattrspi_add_type(args->context,&thang,0); slapi_vattr_values_free(&results, &actual_type_name, free_flags); LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> ID [%s] Type[%s]\n", actual_type_name,type,0); } LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- setTypes \n", 0,0,0); return HT_ENUMERATE_NEXT; } static void logGraphicAttributeValue( Slapi_Attr *attr, const char *attrname ) { Slapi_Value *val = NULL; const struct berval *v = NULL; if ( LDAPDebugLevelIsSet( LDAP_DEBUG_PLUGIN )) { slapi_attr_first_value(attr, &val); v = slapi_value_get_berval(val); if (v) { char *ldifvalue; LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> %s size [%d] \n", attrname,v->bv_len,0); ldifvalue = ldif_type_and_value_with_options( (char *)attrname, /* XXX: had to cast away const */ v->bv_val, v->bv_len, 0 ); if ( NULL != ldifvalue ) { LDAPDebug( LDAP_DEBUG_PLUGIN, "----------> %s value [\n%s]\n", attrname,ldifvalue,0); slapi_ch_free_string( &ldifvalue ); } } } } static void deleteMapTables() { PL_HashTableEnumerateEntries(_IdConfigMapTable, destroyHashEntry, 0); if (_IdConfigMapTable) { PL_HashTableDestroy(_IdConfigMapTable); } PL_HashTableEnumerateEntries(_IdVattrMapTable, destroyHashEntry, 0); if (_IdVattrMapTable) { PL_HashTableDestroy(_IdVattrMapTable); } return; } static PRIntn destroyHashEntry(PLHashEntry *he, PRIntn index, void *arg) { void *value = NULL; if (he == NULL) { return HT_ENUMERATE_NEXT; } value = he->value; if (value) { slapi_ch_free(&value); } return HT_ENUMERATE_REMOVE; } static void toLowerCase(char* str) { if (str) { char* lstr = str; for(; (*lstr != '\0'); ++lstr) { *lstr = tolower(*lstr); } } } /** * utility function to print the array */ void printMapTable() { PL_HashTableEnumerateEntries(_IdVattrMapTable, printIdVattrMapTable, 0); PL_HashTableEnumerateEntries(_IdConfigMapTable, printIdConfigMapTable, 0); } PRIntn printIdVattrMapTable(PLHashEntry *he, PRIntn i, void *arg) { char *key = (char *)he->key; _Vmap *map = (_Vmap *)he->value; printf("<---- Key -------> %s\n", key); printf("<---- ImId ------> %s\n", map->imID); printf("<---- syntax ----> %d\n", map->syntax); return HT_ENUMERATE_NEXT; } PRIntn printIdConfigMapTable(PLHashEntry *he, PRIntn i, void *arg) { char *key = (char *)he->key; _ConfigEntry *value = (_ConfigEntry *)he->value; printf("<- Key ---------------------> %s\n", key); printf("<---- text_url -------------> %s\n", value->textURL); printf("<---- graphic_url ----------> %s\n", value->graphicURL); printf("<---- on_text_map ----------> %s\n", value->onTextMap); printf("<---- off_text_map ---------> %s\n", value->offTextMap); printf("<---- request_method -------> %s\n", value->requestMethod); printf("<---- text_return_type -----> %s\n", value->textReturnType); printf("<---- graphic_return_type --> %s\n", value->graphicReturnType); return HT_ENUMERATE_NEXT; }