cmtevent.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:15k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* 
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "cmtcmn.h"
  35. #include "cmtutils.h"
  36. #include "messages.h"
  37. #include <string.h>
  38. #ifdef XP_UNIX
  39. #include <sys/time.h>
  40. #endif
  41. /* Typedefs */
  42. typedef void (*taskcompleted_handler_fn)(CMUint32 resourceID, CMUint32 numReqProcessed, CMUint32 resultCode, void* data);
  43. CMTStatus CMT_SetUIHandlerCallback(PCMT_CONTROL control, 
  44.                                    uiHandlerCallback_fn f, void *data)
  45. {
  46.     return CMT_RegisterEventHandler(control, SSM_UI_EVENT, 0,
  47.                                     (void_fun)f, data);
  48. }
  49. void CMT_SetFilePathPromptCallback(PCMT_CONTROL control,
  50.                                    filePathPromptCallback_fn f, void* arg)
  51. {
  52.     control->userFuncs.promptFilePath = f;
  53.     control->userFuncs.filePromptArg  = arg;
  54. }
  55. void CMT_SetPromptCallback(PCMT_CONTROL control, 
  56.                            promptCallback_fn f, void *arg)
  57. {
  58.     control->userFuncs.promptCallback = f;
  59.     control->userFuncs.promptArg      = arg;
  60. }
  61. void CMT_SetSavePrefsCallback(PCMT_CONTROL control, savePrefsCallback_fn f)
  62. {
  63.     control->userFuncs.savePrefs = f;
  64. }
  65. CMTStatus CMT_RegisterEventHandler(PCMT_CONTROL control, CMUint32 type, 
  66.                                    CMUint32 resourceID, void_fun handler, 
  67.                                    void* data)
  68. {
  69.     PCMT_EVENT ptr;
  70.     /* This is the first connection */
  71.     if (control->cmtEventHandlers == NULL) {
  72.         control->cmtEventHandlers = ptr = 
  73.             (PCMT_EVENT)calloc(sizeof(CMT_EVENT), 1);
  74.         if (!ptr) {
  75.             goto loser;
  76.         }
  77.     } else {
  78.         /* Look for another event handler of the same type.  Make sure the
  79.            event handler with a rsrcid of 0 is farther down the list so
  80.    that it doesn't get chosen when there's an event handler for
  81.    a specific rsrcid.
  82.  */
  83. for (ptr=control->cmtEventHandlers; ptr != NULL; ptr = ptr->next) {
  84.             if (ptr->type == type && resourceID != 0) {
  85.                 /* So we've got an event handler that wants to over-ride
  86.                    an existing event handler.  We'll put it before the one
  87.                    that's already here.
  88.                  */
  89.                 if (ptr->previous == NULL) {
  90.                     /* We're going to insert at the front of the list*/
  91.                     control->cmtEventHandlers = ptr->previous = 
  92.                         (PCMT_EVENT)calloc(sizeof(CMT_EVENT), 1);
  93.                     if (ptr->previous == NULL) {
  94.                         goto loser;
  95.     }
  96.     ptr->previous->next = ptr;
  97.     ptr = control->cmtEventHandlers;
  98. } else {
  99.     /* We want to insert in the middle of the list */
  100.     PCMT_EVENT tmpEvent;
  101.     
  102.     tmpEvent = (PCMT_EVENT)calloc(sizeof(CMT_EVENT), 1);
  103.     if (tmpEvent == NULL) {
  104.         goto loser;
  105.     }
  106.     tmpEvent->previous  = ptr->previous;
  107.     ptr->previous->next = tmpEvent;
  108.     tmpEvent->next      = ptr;
  109.     ptr->previous       = tmpEvent;
  110.     ptr = tmpEvent;
  111. }
  112. break;
  113.     }
  114.     if (ptr->next == NULL) break;
  115. }
  116. if (ptr == NULL) {
  117.     goto loser;
  118. }
  119. if (ptr->next == NULL) {
  120.     /* We're adding the event handler at the end of the list. */
  121.     ptr->next = (PCMT_EVENT)calloc(sizeof(CMT_EVENT), 1);
  122.     if (!ptr->next) {
  123.         goto loser;
  124.     } 
  125.     /* Fix up the pointers */
  126.     ptr->next->previous = ptr;
  127.     ptr = ptr->next;
  128. }
  129.     }
  130.     /* Fill in the data */
  131.     ptr->type = type;
  132.     ptr->resourceID = resourceID;
  133.     ptr->handler = handler;
  134.     ptr->data = data;
  135.     
  136.     return CMTSuccess;
  137.  loser:
  138.     return CMTFailure;
  139. }
  140. CMTStatus CMT_UnregisterEventHandler(PCMT_CONTROL control, CMUint32 type, 
  141.                                      CMUint32 resourceID) 
  142. {
  143.     PCMT_EVENT ptr, pptr = NULL;
  144.     
  145.     for (ptr = control->cmtEventHandlers; ptr != NULL;
  146.  pptr = ptr, ptr = ptr->next) {
  147.         if ((ptr->type == type) && (ptr->resourceID == resourceID)) {
  148.     if (pptr == NULL) {
  149.         /* node is at head */
  150.         control->cmtEventHandlers = ptr->next;
  151.             if (control->cmtEventHandlers != NULL) {
  152.                 control->cmtEventHandlers->previous = NULL;
  153.             }
  154.             free(ptr);
  155.             return CMTSuccess;
  156.     }
  157.     /* node is elsewhere */
  158.     pptr->next = ptr->next;
  159.         if (ptr->next != NULL) {
  160.             ptr->next->previous = pptr;
  161.         }
  162.     free(ptr);
  163.     return CMTSuccess;
  164.         }
  165.     }
  166.     return CMTFailure;
  167. }
  168. PCMT_EVENT CMT_GetEventHandler(PCMT_CONTROL control, CMUint32 type, 
  169.                                CMUint32 resourceID)
  170. {
  171.     PCMT_EVENT ptr;
  172.     
  173.     for (ptr = control->cmtEventHandlers; ptr != NULL; ptr = ptr->next) {
  174.         if ((ptr->type == type) && ((ptr->resourceID == resourceID) || 
  175.                                     !ptr->resourceID)) {
  176.             return ptr;
  177.         }
  178.     }
  179.     return NULL;
  180. }
  181. PCMT_EVENT CMT_GetFirstEventHandler(PCMT_CONTROL control, CMUint32 type, 
  182.                                     CMUint32 resourceID)
  183. {
  184.     PCMT_EVENT ptr;
  185.     for (ptr = control->cmtEventHandlers; ptr != NULL; ptr = ptr->next) {
  186.         if ((ptr->type == type) && ((ptr->resourceID == resourceID) || 
  187.                                     !ptr->resourceID)) {
  188.             return ptr;
  189.         }
  190.     }
  191.     return NULL;
  192. }
  193. PCMT_EVENT CMT_GetNextEventHandler(PCMT_CONTROL control, PCMT_EVENT e)
  194. {
  195.     PCMT_EVENT ptr;
  196.     for (ptr = control->cmtEventHandlers; ptr != NULL || ptr == e; 
  197.          ptr = ptr->next) {
  198.     }
  199.     for (; ptr != NULL; ptr = ptr->next) {
  200.         if ((ptr->type == e->type) && ((ptr->resourceID == e->resourceID) || 
  201.                                        !ptr->resourceID)) {
  202.             return ptr;
  203.         }
  204.     }
  205.     return NULL;
  206. }
  207. void CMT_ProcessEvent(PCMT_CONTROL cm_control)
  208. {
  209.     CMTSocket sock; 
  210.     CMTItem eventData={ 0, NULL, 0 };
  211.     /* Get the control socket */
  212.     sock = cm_control->sock;
  213.     /* Acquire a lock on the control connection */
  214.     CMT_LOCK(cm_control->mutex);
  215.     /* Do another select here to be sure 
  216.        that the socket is readable */
  217.     if (cm_control->sockFuncs.select(&sock, 1, 1) != sock) {
  218.         /* There's no event. */
  219.         goto done;
  220.     }
  221.     /* Read the event */
  222.     if (CMT_ReceiveMessage(cm_control, &eventData) == CMTFailure) {
  223.         goto done;
  224.     }
  225.     CMT_UNLOCK(cm_control->mutex);
  226.     /* Dispatch the event */
  227.     CMT_DispatchEvent(cm_control, &eventData);
  228.     return;
  229. done:
  230.     /* Release the lock on the control connection */
  231.     CMT_UNLOCK(cm_control->mutex);
  232. }
  233. void CMT_EventLoop(PCMT_CONTROL cm_control)
  234. {
  235.     CMTSocket sock;
  236.     /* Get the control socket */
  237.     sock = cm_control->sock;
  238.     CMT_ReferenceControlConnection(cm_control);
  239.     /* Select on the control socket to see if it's readable */
  240.     while(cm_control->sockFuncs.select(&sock, 1, 0)) {
  241.       CMT_ProcessEvent(cm_control);
  242.     }
  243.     CMT_CloseControlConnection(cm_control);
  244.     return;
  245. }
  246. void
  247. CMT_PromptUser(PCMT_CONTROL cm_control, CMTItem *eventData)
  248. {
  249.     char *promptReply  = NULL;
  250.     CMTItem   response={ 0, NULL, 0 };
  251.     PromptRequest request;
  252.     PromptReply reply;
  253.     void * clientContext;
  254.     /* Decode the message */
  255.     if (CMT_DecodeMessage(PromptRequestTemplate, &request, eventData) != CMTSuccess) {
  256.         goto loser;
  257.     }
  258.     /* Copy the client context to a pointer */
  259.     clientContext = CMT_CopyItemToPtr(request.clientContext);
  260.     if (cm_control->userFuncs.promptCallback == NULL) {
  261.         goto loser;
  262.     }
  263.     promptReply = 
  264.         cm_control->userFuncs.promptCallback(cm_control->userFuncs.promptArg, 
  265.                                              request.prompt, clientContext, 1);
  266.     response.type = SSM_EVENT_MESSAGE | SSM_PROMPT_EVENT;
  267.     if (!promptReply) {
  268.         /* the user canceled the prompt or other errors occurred */
  269.         reply.cancel = CM_TRUE;
  270.     }
  271.     else {
  272.         /* note that this includes an empty string (zero length) password */
  273.         reply.cancel = CM_FALSE;
  274.     }
  275.     reply.resID = request.resID;
  276.     reply.promptReply = promptReply;
  277.     /* Encode the message */
  278.     if (CMT_EncodeMessage(PromptReplyTemplate, &response, &reply) != CMTSuccess) {
  279.         goto loser;
  280.     }
  281.     CMT_TransmitMessage(cm_control, &response);
  282.  loser:
  283.     if (promptReply != NULL) {
  284.       cm_control->userFuncs.userFree(promptReply);
  285.     }
  286.     return;
  287. }
  288. void CMT_GetFilePath(PCMT_CONTROL cm_control, CMTItem * eventData)
  289. {
  290.     char *fileName=NULL;
  291.     CMTItem response = { 0, NULL, 0 };
  292.     FilePathRequest request;
  293.     FilePathReply reply;
  294.     /* Decode the request */
  295.     if (CMT_DecodeMessage(FilePathRequestTemplate, &request, eventData) != CMTSuccess) {
  296.         goto loser;
  297.     }
  298.     if (cm_control->userFuncs.promptFilePath == NULL) {
  299.         goto loser;
  300.     }
  301.     fileName = 
  302.      cm_control->userFuncs.promptFilePath(cm_control->userFuncs.filePromptArg,
  303.                                           request.prompt, request.fileRegEx, 
  304.                                           request.getExistingFile);
  305.     response.type = SSM_EVENT_MESSAGE | SSM_FILE_PATH_EVENT;
  306.     reply.resID = request.resID;
  307.     reply.filePath = fileName;
  308.     /* Encode the reply */
  309.     if (CMT_EncodeMessage(FilePathReplyTemplate, &response, &reply) != CMTSuccess) {
  310.         goto loser;
  311.     }
  312.     CMT_TransmitMessage(cm_control, &response);
  313.     cm_control->userFuncs.userFree(fileName); 
  314. loser:
  315.    return;
  316. }
  317. void CMT_SavePrefs(PCMT_CONTROL cm_control, CMTItem* eventData)
  318. {
  319.     SetPrefListMessage request;
  320.     int i;
  321.     /* decode the request */
  322.     if (CMT_DecodeMessage(SetPrefListMessageTemplate, &request, eventData) !=
  323.         CMTSuccess) {
  324.         return;
  325.     }
  326.     if (cm_control->userFuncs.savePrefs == NULL) {
  327.         /* callback was not registered: bail */
  328.         return;
  329.     }
  330.     cm_control->userFuncs.savePrefs(request.length, 
  331.                                     (CMTSetPrefElement*)request.list);
  332.     for (i = 0; i < request.length; i++) {
  333.         if (request.list[i].key != NULL) {
  334.             free(request.list[i].key);
  335.         }
  336.         if (request.list[i].value != NULL) {
  337.             free(request.list[i].value);
  338.         }
  339.     }
  340.     return;
  341. }
  342. void CMT_DispatchEvent(PCMT_CONTROL cm_control, CMTItem * eventData)
  343. {
  344.     CMUint32 eventType;
  345.     CMTItem msgCopy;
  346.     /* Init the msgCopy */
  347.     msgCopy.data = 0;    
  348.     /* Get the event type */
  349.     if ((eventData->type & SSM_CATEGORY_MASK) != SSM_EVENT_MESSAGE) {
  350.         /* Somehow there was a message on the socket that was not 
  351.          * an event message.  Dropping it on the floor.
  352.          */
  353.         goto loser;
  354.     }
  355.     eventType = (eventData->type & SSM_TYPE_MASK);
  356.     /* We must now dispatch the event based on it's type */
  357.     switch (eventType) {
  358.         case SSM_UI_EVENT:
  359.         {
  360.             PCMT_EVENT p;
  361.             UIEvent event;
  362.             void * clientContext = NULL;
  363.     /* Copy the message to allow a second try with the old format */
  364.     msgCopy.len = eventData->len;
  365.     msgCopy.data = calloc(msgCopy.len, 1);
  366.     if (msgCopy.data) {
  367.               memcpy(msgCopy.data, eventData->data, eventData->len);
  368.     }
  369.             /* Get the event data first */
  370.             if (CMT_DecodeMessage(UIEventTemplate, &event, eventData) != CMTSuccess) {
  371. /* Attempt to decode using the old format.  Modal is True */
  372. if (!msgCopy.data || 
  373.     CMT_DecodeMessage(OldUIEventTemplate, &event, &msgCopy) != CMTSuccess) {
  374.                   goto loser;
  375.                 }
  376.                 /* Set default modal value */
  377.                 event.isModal = CM_TRUE;
  378.             }
  379.             /* Convert the client context to a pointer */
  380.             clientContext = CMT_CopyItemToPtr(event.clientContext);
  381.             /* Call any handlers for this event */
  382.             p = CMT_GetEventHandler(cm_control, eventType, event.resourceID);
  383.             if (!p) {
  384.                 goto loser;
  385.             }
  386.             (*(uiHandlerCallback_fn)(p->handler))(event.resourceID, 
  387.                                                   clientContext, event.width,
  388.                                                   event.height, event.isModal, event.url, 
  389.                                                   p->data);
  390.             break;
  391.         }
  392.         case SSM_TASK_COMPLETED_EVENT:
  393.         {
  394.            PCMT_EVENT p;
  395.            TaskCompletedEvent event;
  396.             /* Get the event data */
  397.             if (CMT_DecodeMessage(TaskCompletedEventTemplate, &event, eventData) != CMTSuccess) {
  398.                 goto loser;
  399.             }
  400.             /* Call handler for this event */
  401.             p = CMT_GetEventHandler(cm_control, eventType, event.resourceID);
  402.             if (!p) {
  403.                 goto loser;
  404.             }
  405.             (*(taskcompleted_handler_fn)(p->handler))(event.resourceID, 
  406.                                                       event.numTasks, 
  407.                                                       event.result, p->data);
  408.             break;
  409.         }
  410.         case SSM_AUTH_EVENT: 
  411.              CMT_ServicePasswordRequest(cm_control, eventData);
  412.              break;
  413.         case SSM_FILE_PATH_EVENT:
  414.           CMT_GetFilePath(cm_control, eventData);
  415.              break;
  416.         case SSM_PROMPT_EVENT:
  417.          CMT_PromptUser(cm_control, eventData);
  418.          break;
  419.         case SSM_SAVE_PREF_EVENT:
  420.             CMT_SavePrefs(cm_control, eventData);
  421.             break;
  422.         default:
  423.             break;
  424.     }
  425. loser:
  426.     free(eventData->data);
  427.     free(msgCopy.data);
  428.     return;
  429. }