/**************************************************************************** * NCSA Mosaic for the X Window System * * Software Development Group * * National Center for Supercomputing Applications * * University of Illinois at Urbana-Champaign * * 605 E. Springfield, Champaign IL 61820 * * mosaic@ncsa.uiuc.edu * * * * Copyright (C) 1993, Board of Trustees of the University of Illinois * * * * NCSA Mosaic software, both binary and source (hereafter, Software) is * * copyrighted by The Board of Trustees of the University of Illinois * * (UI), and ownership remains with the UI. * * * * The UI grants you (hereafter, Licensee) a license to use the Software * * for academic, research and internal business purposes only, without a * * fee. Licensee may distribute the binary and source code (if released) * * to third parties provided that the copyright notice and this statement * * appears on all copies and that no charge is associated with such * * copies. * * * * Licensee may make derivative works. However, if Licensee distributes * * any derivative work based on or derived from the Software, then * * Licensee will (1) notify NCSA regarding its distribution of the * * derivative work, and (2) clearly notify users that such derivative * * work is a modified version and not the original NCSA Mosaic * * distributed by the UI. * * * * Any Licensee wishing to make commercial use of the Software should * * contact the UI, c/o NCSA, to negotiate an appropriate license for such * * commercial use. Commercial use includes (1) integration of all or * * part of the source code into a product for sale or license by or on * * behalf of Licensee to third parties, or (2) distribution of the binary * * code or source code to third parties that need it to utilize a * * commercial product sold or licensed by or on behalf of Licensee. * * * * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR * * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED * * WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE * * USERS OF THIS SOFTWARE. * * * * By using or copying this Software, Licensee agrees to abide by the * * copyright law and all other applicable laws of the U.S. including, but * * not limited to, export control laws, and the terms of this license. * * UI shall have the right to terminate this license immediately by * * written notice upon Licensee's breach of, or non-compliance with, any * * of its terms. Licensee may be held legally responsible for any * * copyright infringement that is caused or encouraged by Licensee's * * failure to abide by the terms of this license. * * * * Comments and questions are welcome and can be sent to * * mosaic-x@ncsa.uiuc.edu. * ****************************************************************************/ #include #include #include #include "mosaic.h" #include "gui.h" #include "cci.h" #include "cciBindings2.h" #include #include "cciServer.h" #include "list.h" #include "memStuffForPipSqueeks.h" #include #include "libwww2/HTFormat.h" static Boolean cciAccepting = 0; static int listenPortNumber=0; static XtInputId connectInputID; static List listOfConnections; static List listOfSendOutput; static List listOfSendAnchorTo; /* client in list if should receive */ static List listOfSendBrowserView; static List listOfSendEvent; static List listOfFileToURLs; static List listOfForm; /* list of form submitted by application */ /* ADC ugly hack below ZZZZZ */ extern int CCIprotocol_handler_found; extern int MCCIanchorcached; extern XtAppContext app_context; /***/ extern HTStream* CCIPresent(); extern char *machine_with_domain; /* host name */ /* from cciBindings.c */ extern int cci_event; #ifndef DISABLE_TRACE extern int cciTrace; #endif struct Connection { XtInputId inputId; MCCIPort client; }; struct SendWhatToWhom { MCCIPort client; char *contentType; }; struct FileURL { char *fileName; char *url; }; struct FormSubmit{ MCCIPort client; char *actionID; int valid; }; cciStat *cciStatListFindEntry(MCCIPort findMe) { /* this finds an entry in listOfSendAnchorTo based on MCCIPort client. */ cciStat *current; char notDone = 1; current = (cciStat *) ListHead(listOfSendAnchorTo); while (notDone) { if ((current == NULL) || (current->client == findMe)) notDone = 0; else current = (cciStat *) ListNext(listOfSendAnchorTo); } return current; } cciStat *cciStatListDeleteEntry(MCCIPort deleteMe) { cciStat *current; if (current = cciStatListFindEntry(deleteMe)) { ListDeleteEntry(listOfSendAnchorTo,current); return current; } else return NULL; } void cciStatPreventSendAnchor(MCCIPort client, char *url) { /* this sets the flag that is checked for in cciSafeToSend, but * only if sendAnchor is on for this client. */ cciStat *current; if ((current = cciStatListFindEntry(client)) && (url != NULL)) current->url = strdup(url); } int cciSafeToSend(cciStat *current, char *url) { /* ensures that Mosaic does not send an ANCHOR in response to a GET * if SEND ANCHOR is turned on. * * INPUTS: * url The url for which the flag is to be set. * RETURNS: * returns 0 if flag set for (client,url) pair (not safe to send) * 1 if flag is not set for (client,url) pair * (safe to send) */ int rc = 1; if (current->url != NULL) { rc = strcmp(url,current->url); free(current->url); current->url = NULL; } return rc; } void cciStatFree(cciStat *i) { free(i); } cciStat *cciStatNew(MCCIPort client, int status) { cciStat *new; new = (cciStat *) malloc( sizeof(cciStat) ); if (new) { new->client = client; new->status = status; new->url = NULL; } return new; } void MoCCISendAnchor(client,sendIt) /* set the state of sending anchors */ MCCIPort client; int sendIt; /* 0, don't send, 1 send before browser gets document, */ /* 2 send after browser gets document */ /* 3 send it before and then let the CCI app handle it ADC ZZZ */ { cciStat *statElt; statElt = cciStatListDeleteEntry(client); switch (sendIt) { case 0: if (statElt) cciStatFree(statElt); break; case 1: /* send before browser gets document */ if (statElt) statElt->status = 1; else statElt = cciStatNew(client,1); if (statElt) ListAddEntry(listOfSendAnchorTo,statElt); break; case 2: /* send after browser gets document */ if (statElt) statElt->status = 2; else statElt = cciStatNew(client,2); if (statElt) ListAddEntry(listOfSendAnchorTo,statElt); break; case 3: /* send before browser gets document, then let it handle it ADC ZZZ */ if (statElt) statElt->status = 3; else statElt = cciStatNew(client,3); if (statElt) ListAddEntry(listOfSendAnchorTo,statElt); break; default: ; } } void MoCCISendAnchorToCCI(url, beforeAfter) char *url; int beforeAfter; /*************************************************************** * beforeAfter - 0: send to all clients in list * 1: send to all clients with status == 1; * 2: send to all clients with status == 2: * 3: send to all clients with status == 3: ADC ZZZ ***************************************************************/ { cciStat *client; client = (cciStat *) ListHead(listOfSendAnchorTo); while(client) { if (cciSafeToSend(client, url)) /* test flag */ switch (beforeAfter) { case 0: if (client->status == 3) { /* ADC ZZZ */ MCCIanchorcached = 1; MCCISendAnchorHistory(client->client,url); MCCIanchorcached = 0; } else MCCISendAnchorHistory(client->client,url); break; case 1: if (client->status == 1) MCCISendAnchorHistory(client->client,url); break; case 2: if (client->status == 2) MCCISendAnchorHistory(client->client,url); case 3: /* ADC ZZZ */ if (client->status == 3) MCCISendAnchorHistory(client->client,url); CCIprotocol_handler_found = 1; break; default: ; } client = (cciStat *) ListNext(listOfSendAnchorTo); } } void MoCCISendEvent(client,on) MCCIPort client; int on; { MCCIPort tmp; if (on) { ListAddEntry(listOfSendEvent,client); } else { ListDeleteEntry(listOfSendEvent,client); /* turn off cci_event only if list of clients is NULL */ if (!(tmp = (MCCIPort) ListHead(listOfSendEvent))) cci_event = 0; } } void MoCCISendMouseAnchor(client,on) MCCIPort client; int on; { MCCIPort tmp; if (on) { ListAddEntry(listOfSendEvent,client); } else { ListDeleteEntry(listOfSendEvent,client); /* turn off cci_event only if list of clients is NULL */ if (!(tmp = (MCCIPort) ListHead(listOfSendEvent))) cci_event = 0; } } void MoCCISendBrowserView(client,on) MCCIPort client; int on; { if (on) { ListAddEntry(listOfSendBrowserView,client); } else { ListDeleteEntry(listOfSendBrowserView,client); } } void MoCCIForm(client, actionID, status,close_connection) MCCIPort client; char *actionID; int status; int close_connection; { struct FormSubmit *sendForm; int registered = 0; if (status){ sendForm = (struct FormSubmit *) ListHead(listOfForm); while (sendForm){ if ((sendForm->client == client) && (!strcmp(sendForm->actionID,actionID))) { sendForm->valid = 1; registered = 1; } sendForm = (struct FormSubmit *)ListNext(listOfForm); } /* only register if not done so alreday */ if (!registered){ if (!(sendForm = (struct FormSubmit *) MALLOC(sizeof(struct FormSubmit)))) { return; /* mem problem */ } sendForm->client = client; sendForm->actionID = strdup(actionID); sendForm->valid = 1; ListAddEntry(listOfForm, sendForm); } } else if (close_connection) { sendForm = (struct FormSubmit *) ListHead(listOfForm); while(sendForm){ if (sendForm->client == client) { ListDeleteEntry(listOfForm, sendForm); FREE(sendForm->actionID); FREE(sendForm); sendForm = (struct FormSubmit *) ListCurrent(listOfForm); #if 0 sendForm->valid = 0; #endif } else{ sendForm = (struct FormSubmit *) ListNext(listOfForm); } } } else{ /* remove entry from list, forget the valid bit, delete it!! */ sendForm = (struct FormSubmit *) ListHead(listOfForm); while(sendForm){ if ((sendForm->client == client) && (!strcmp(sendForm->actionID,actionID))){ ListDeleteEntry(listOfForm, sendForm); FREE(sendForm->actionID); FREE(sendForm); sendForm = (struct FormSubmit *) ListCurrent(listOfForm); #if 0 sendForm->valid = 0; #endif } else{ sendForm = (struct FormSubmit *) ListNext(listOfForm); } } } #ifndef DISABLE_TRACE if (cciTrace) { sendForm = (struct FormSubmit *) ListHead(listOfForm); fprintf(stderr,"***** begin mosaic list *****\n"); while(sendForm){ fprintf(stderr,"actionID %s\n",sendForm->actionID); fprintf(stderr,"clientaddress %s\n",sendForm->client->serverAddress); sendForm = (struct FormSubmit *) ListNext(listOfForm); } } #endif } int MoCCIPreInitialize() { static int donePreInit = 0; if (donePreInit) { return 0; } donePreInit = 1; listOfConnections = ListCreate(); listOfSendOutput = ListCreate(); listOfSendAnchorTo = ListCreate(); listOfSendBrowserView = ListCreate(); listOfSendEvent = ListCreate(); listOfFileToURLs = ListCreate(); listOfForm = ListCreate(); } int MoCCIInitialize(portNumber) int portNumber; { int retVal; MoCCIPreInitialize(); retVal = MCCIServerInitialize(portNumber); if (retVal) { /* Write port number to .mosaiccciport */ char *home = flatpakCheck(), *fnam; FILE *fp; if (!home) home = "/tmp"; fnam = (char *)malloc (strlen (home) + 32); sprintf (fnam, "%s/cciport", home); // SAM fp = fopen (fnam, "w"); if (fp) { fprintf(fp,"%s:%d\n",machine_with_domain,portNumber); fclose (fp); } free (fnam); } return(retVal); } int MoCCITerminateAllConnections() { struct Connection *con; struct SendWhatToWhom *sendOutput; con = (struct Connection *) ListHead(listOfConnections); while(con) { XtRemoveInput(con->inputId); NetCloseConnection(con->client); MoCCISendAnchor(con->client,0); MoCCISendBrowserView(con->client,0); MoCCISendEvent(con->client, 0); MoCCIForm(con->client, NULL, 0, 1); sendOutput=(struct SendWhatToWhom *)ListHead(listOfSendOutput); while(sendOutput){ /* remove sendOutputs */ HTRemoveConversion(sendOutput->contentType, "www/present",CCIPresent); ListDeleteEntry(listOfSendOutput,sendOutput); FREE(sendOutput->contentType); FREE(sendOutput); sendOutput = (struct SendWhatToWhom *) ListCurrent(listOfSendOutput); } ListDeleteEntry(listOfConnections,con); con = (struct Connection *) ListHead(listOfConnections); } } int MoCCITerminateAConnection(client) MCCIPort client; { struct Connection *con; struct SendWhatToWhom *sendOutput; con = (struct Connection *) ListHead(listOfConnections); while(con) { if (con->client == client) { XtRemoveInput(con->inputId); MoCCISendAnchor(con->client,0); MoCCISendBrowserView(con->client,0); MoCCISendEvent(con->client, 0); MoCCIForm(con->client, NULL, 0, 1); sendOutput=(struct SendWhatToWhom *) ListHead(listOfSendOutput); while(sendOutput){ /* remove sendOutputs */ if(sendOutput->client == client){ HTRemoveConversion(sendOutput->contentType, "www/present",CCIPresent); ListDeleteEntry(listOfSendOutput,sendOutput); FREE(sendOutput->contentType); FREE(sendOutput); } sendOutput = (struct SendWhatToWhom *) ListNext(listOfSendOutput); } ListDeleteEntry(listOfConnections,con); con = (struct Connection *) ListCurrent(listOfConnections); } else { con = (struct Connection *) ListNext(listOfConnections); } } } void MoCCIHandleInput(client,source) MCCIPort client; int source; { if (MCCIIsThereInput(client)) { MCCIHandleInput(client); } } void MoCCINewConnection(app_context,source,inputID) XtAppContext app_context; int *source; XtInputId *inputID; { MCCIPort client; struct Connection *con; #ifndef DISABLE_TRACE if (cciTrace) { fprintf(stderr,"MoCCINewConnection(): I've been called\n"); } #endif client = MCCICheckAndAcceptConnection(); if (!client) { /* nothing here */ return; } #ifndef DISABLE_TRACE if (cciTrace) { fprintf(stderr,"Mosaic: got a CCI connection\n"); } #endif /* this determines wether there is one or many cci clients connecting XtRemoveInput(*inputID); */ MCCISendResponseLine(client,MCCIR_OK,"VERSION 01 X Mosaic 2.7b5"); con = (struct Connection *) malloc(sizeof(struct Connection)); con->client = client; con->inputId = XtAppAddInput(app_context, MCCIGetSocketDescriptor(client), (XtPointer) XtInputReadMask, (XtInputCallbackProc) MoCCIHandleInput, (XtPointer) client); ListAddEntry(listOfConnections,con); } static XmxCallback (MoCCIWindowCallBack) { Boolean newState; mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data)); int newPort; char *portString; char buff[256]; newState = cciAccepting; switch (XmxExtractToken ((int)client_data)) { case 0: /*ok*/ newState = XmToggleButtonGetState(win->cci_accept_toggle); XtUnmanageChild(win->cci_win); break; case 1: /*Cancel*/ if (cciAccepting != XmToggleButtonGetState (win->cci_accept_toggle)) { /* reset toggle state */ XmxSetToggleButton(win->cci_accept_toggle, cciAccepting); XmxSetToggleButton(win->cci_off_toggle, !cciAccepting); } XtUnmanageChild(win->cci_win); break; case 2: /*Help*/ mo_open_another_window (win, mo_assemble_help_url("docview-menubar-file.html#open"), NULL, NULL); break; } if (newState != cciAccepting) { /* toggle state has changed */ cciAccepting = newState; if (cciAccepting) { newPort = 0; portString= XmxTextGetString (win->cci_win_text); if (portString) { newPort = atoi(portString); } if ((newPort < 1024) || (newPort > 65535)) { XmxMakeErrorDialog (win->cci_win, "CCI port address must be between 1024 and 65535" , "CCI port address error" ); XtManageChild (Xmx_w); cciAccepting = False; listenPortNumber = 0; XmxSetToggleButton(win->cci_accept_toggle, cciAccepting); XmxSetToggleButton(win->cci_off_toggle, !cciAccepting); return; } if (MoCCIInitialize(newPort)) { listenPortNumber = newPort; connectInputID = XtAppAddInput(app_context, MCCIReturnListenPortSocketDescriptor(), (XtPointer) XtInputReadMask, (XtInputCallbackProc) MoCCINewConnection, app_context); sprintf(buff,"%s %d","CCI Now listening on port" ,newPort); XmxMakeInfoDialog(win->cci_win,buff,"CCI port status" ); XtManageChild(Xmx_w); } else { cciAccepting = False; listenPortNumber = 0; XmxSetToggleButton(win->cci_accept_toggle, cciAccepting); XmxSetToggleButton(win->cci_off_toggle, !cciAccepting); /* Can't accept on this port...*/ XmxMakeErrorDialog (win->cci_win, "CCI Can't accept requests on this port. May be in use already." , "CCI port address error" ); XtManageChild(Xmx_w); } } else { XtRemoveInput(connectInputID); /* stop accepting connections*/ MCCICloseAcceptPort(); /* kill accept port */ /* terminate existing connections */ MoCCITerminateAllConnections(); listenPortNumber = 0; sprintf(buff,"CCI Is no longer listening"); XmxMakeInfoDialog(win->cci_win, buff,"CCI port status"); XtManageChild(Xmx_w); } } } mo_status MoDisplayCCIWindow(win) mo_window *win; { Widget dialogFrame; Widget dialogSeparator; /*Widget buttonsForm;*/ Widget cciForm,label; Widget toggleBox; Widget buttonBox; if (!win->cci_win) { XmxSetUniqid (win->id); win->cci_win = XmxMakeFormDialog(win->base, "NCSA Mosaic: Common Client Interface" ); dialogFrame = XmxMakeFrame(win->cci_win, XmxShadowOut); XmxSetConstraints (dialogFrame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, NULL, NULL, NULL, NULL); /* Main form. */ cciForm = XmxMakeForm(dialogFrame); label = XmxMakeLabel(cciForm, "CCI Port Address: " ); XmxSetArg(XmNcolumns, 25); win->cci_win_text= XmxMakeText (cciForm); XmxAddCallbackToText (win->cci_win_text, MoCCIWindowCallBack, 0); toggleBox = XmxMakeRadioBox(cciForm); win->cci_accept_toggle = XmxMakeToggleButton (toggleBox, "Accept requests" , NULL, 0); win->cci_off_toggle = XmxMakeToggleButton (toggleBox, "Interface off" , NULL, 0); dialogSeparator= XmxMakeHorizontalSeparator(cciForm); buttonBox = XmxMakeFormAndThreeButtons(cciForm, MoCCIWindowCallBack, "Ok" , "Dismiss" , "Help..." , 0,1,2); XmxSetOffsets (label, 13, 0, 10, 0); XmxSetConstraints (label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE, NULL, NULL, NULL, NULL); XmxSetOffsets (win->cci_win_text, 10, 0, 5, 8); XmxSetConstraints (win->cci_win_text, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_FORM, NULL, NULL, label, NULL); XmxSetConstraints (toggleBox, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_NONE, win->cci_win_text, NULL, label, NULL); XmxSetOffsets (toggleBox, 8, 0, 2, 0); XmxSetConstraints (dialogSeparator, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, toggleBox, NULL, NULL, NULL); XmxSetConstraints (buttonBox, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, dialogSeparator, NULL, NULL, NULL); } if (cciAccepting) { char buff[10]; sprintf(buff,"%d",listenPortNumber); XmxTextSetString(win->cci_win_text,buff); } else { XmxTextSetString(win->cci_win_text,""); } XmxSetToggleButton(win->cci_accept_toggle, cciAccepting); XmxSetToggleButton(win->cci_off_toggle, !cciAccepting); XmxManageRemanage (win->cci_win); return mo_succeed; } void MoCCISendOutputToClient(contentType,fileName) char *contentType; /* string name of data type */ char *fileName; /* data stored here */ { struct SendWhatToWhom *sendOutput; /* send data to all clients that registered for this content type*/ sendOutput=(struct SendWhatToWhom *)ListHead(listOfSendOutput); while(sendOutput){ if (!strcmp(sendOutput->contentType,contentType)) { #ifndef DISABLE_TRACE if (cciTrace) { fprintf(stderr,"Sending output through cci of type %s\n", sendOutput->contentType); } #endif /* prep data for sending here */ /* send it back to client */ MCCISendOutputFile(sendOutput->client, contentType,fileName); } sendOutput=(struct SendWhatToWhom *)ListNext(listOfSendOutput); } return; } /* inorder to send content to application, mosaic must call this function twice, the first to set the variable send, the second to do the actual sending */ int MoCCIFormToClient(actionID, query, contentType, post_data, status) char *actionID; char *query; char *contentType; char *post_data; int status; { static int send = 0; struct FormSubmit *sendForm; int found = 0; /* just make a note that its a cciPOST */ if (status && (send == 0)) { send = 1; return(0); } if (send){ send = 0; sendForm=(struct FormSubmit *) ListHead(listOfForm); while(sendForm) { if ( !strcmp(actionID, sendForm->actionID)) /* found correct client */ { if (sendForm->valid) MCCIFormQueryToClient(sendForm->client, actionID, query, contentType, post_data); found = 1; } sendForm = (struct FormSubmit *)ListNext(listOfForm); } } return found; } /* this function is a callback from the libwww2 Converter */ void MoCCISendOutput(MCCIPort client,Boolean sendIt,char *contentType) { struct SendWhatToWhom *sendOutput; if (sendIt) { if (!(sendOutput = (struct SendWhatToWhom *) MALLOC(sizeof(struct SendWhatToWhom)))) { return /*mem error*/; } sendOutput->client = client; sendOutput->contentType = strdup(contentType); ListAddEntry(listOfSendOutput,sendOutput); /* set up call back for this content Type */ HTSetConversion(contentType,"www/present",CCIPresent, 1.0, 0.0, 0.0); /*If we use this, out put a message like....sent to cci */ /** HTSetPresentation(contentType,MoCCISendOutputCB, 1.0, 0.0, 0.0); */ } else { sendOutput=(struct SendWhatToWhom *)ListHead(listOfSendOutput); while(sendOutput){ if ((sendOutput->client == client) && (!strcmp(sendOutput->contentType,contentType))) { HTRemoveConversion(contentType, "www/present",CCIPresent); ListDeleteEntry(listOfSendOutput,sendOutput); FREE(sendOutput->contentType); FREE(sendOutput); sendOutput = (struct SendWhatToWhom *) ListCurrent(listOfSendOutput); } else { sendOutput = (struct SendWhatToWhom *) ListNext(listOfSendOutput); } } } } void MoCCIStartListening(w,port) Widget w; int port; { /*int listenPort;*/ if (MoCCIInitialize(port)) { connectInputID = XtAppAddInput(app_context, MCCIReturnListenPortSocketDescriptor(), (XtPointer) XtInputReadMask, (XtInputCallbackProc) MoCCINewConnection, app_context); cciAccepting = True; listenPortNumber = port; /* XmxMakeInfoDialog(w,"Mosaic CCI port is listening", "CCI port status"); XtManageChild(Xmx_w); */ } else { char buf[80]; sprintf(buf,"%s %d","Could not listen on port" ,port); XmxMakeErrorDialog(w,buf, "CCI Error" ); XtManageChild(Xmx_w); } } void MoCCISendEventOutput(event_type) /* Handle SendEventOutput if needed */ /* send Event data to all the clients that have requested it */ CCI_events event_type; { MCCIPort client; client = (MCCIPort) ListHead(listOfSendEvent); while (client) { MCCISendEventOutput(client,event_type); client = (MCCIPort) ListNext(listOfSendEvent); } } void MoCCISendMouseAnchorOutput(anchor) /* Handle SendMouseAnchorOutput if needed */ /* send MouseAnchor data to all the clients that have requested it */ char *anchor; { MCCIPort client; client = (MCCIPort) ListHead(listOfSendEvent); while (client) { MCCISendMouseAnchorOutput(client,anchor); client = (MCCIPort) ListNext(listOfSendEvent); } } void MoCCISendBrowserViewOutput(url, contentType, data, dataLength) /* Handle SendBrowserViewOutput if needed */ /* send BrowserView data to all the clients that have requested it */ char *url; char *contentType; char *data; int dataLength; { MCCIPort client; if (dataLength == 0) { return; } if (!data) { return; } if ((!url) || (!strlen(url))) { return; } if ((!contentType) || (!strlen(contentType))) { contentType = "unknown"; } client = (MCCIPort) ListHead(listOfSendBrowserView); while (client) { MCCISendBrowserViewOutput(client,url,contentType, data,dataLength); client = (MCCIPort) ListNext(listOfSendBrowserView); } } int MoCCISendBrowserViewFile(url, contentType, filename) char *url; char *contentType; char *filename; { struct stat fileInfo; FILE *fp; char *data; if (!ListHead(listOfSendBrowserView)) { return(MCCI_OK); } if ((!filename) || (!strlen(filename))) { return(MCCI_OK); } if ((!url) || (!strlen(url))) { return(MCCI_OK); } if ((!contentType) || (!strlen(contentType))) { contentType = "unknown"; } if (stat(filename,&fileInfo)) { /* get the length of the file */ return(MCCI_FAIL); } if (!(fp = fopen(filename,"r"))) { return(MCCI_FAIL); } if (!(data = (char *) malloc(fileInfo.st_size))) { fclose(fp); return(MCCI_OUTOFMEMORY); } if (fileInfo.st_size != fread(data,sizeof(char),fileInfo.st_size,fp)){ fclose(fp); free(data); return(MCCI_FAIL); } MoCCISendBrowserViewOutput(url, contentType, data, fileInfo.st_size); free(data); fclose(fp); return(MCCI_OK); } int MoCCIMaxNumberOfConnectionsAllowed() /* return number of connections allowed. This is set in the X resources. * if it's zero, then treat it as unlimited. */ { return(get_pref_int(eMAX_NUM_OF_CCI_CONNECTIONS)); } int MoCCICurrentNumberOfConnections() { return(ListCount(listOfConnections)); } void MoCCIAddFileURLToList(fileName,url) /* this routine should be called each time a url has been down loaded and stored as file. This routine adds the fileName,url pair to the list for later query over cci by an external viewer (cci app). */ char *fileName; char *url; { struct FileURL *fileURL; #ifndef DISABLE_TRACE if (cciTrace) { fprintf(stderr,"MoCCIAddFileURLToList():fileName=\"%s\", url=\"%s\"\n",(fileName?fileName:"NULL"),(url?url:"NULL")); } #endif if ((!fileName) || (!url)) { return; } if (!(fileURL = (struct FileURL *) MALLOC(sizeof (struct FileURL)))) { /* out of memory, just return */ return; } fileURL->fileName = strdup(fileName); fileURL->url = strdup(url); ListAddEntry(listOfFileToURLs,fileURL); return; } char *MoReturnURLFromFileName(fileName) /* given filename, return associated URL in the list */ /* if not found, return NULL */ char *fileName; { struct FileURL *fileURL; fileURL = (struct FileURL *) ListHead(listOfFileToURLs); while (fileURL){ if (!strncmp(fileURL->fileName,fileName, strlen(fileURL->fileName))) { return(fileURL->url); } fileURL = (struct FileURL *) ListNext(listOfFileToURLs); } return(NULL); } /* this rplaces a vanilla url name with the name it was actually called with, which is what is needed by external apps. It is indeed a huge hack, and should be fixed */ void MoCCIAddAnchorToURL(url, urlAndAnchor) char *url; char *urlAndAnchor; { struct FileURL *fileURL; fileURL = (struct FileURL *) ListTail(listOfFileToURLs); if (fileURL && !strcmp(fileURL->url, url)) { free(fileURL->url); fileURL->url = strdup(urlAndAnchor); } }