1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- *+SNOTICE
- *
- *
- * $TOG: Session.C /main/16 1998/07/24 16:08:39 mgreess $
- *
- * RESTRICTED CONFIDENTIAL INFORMATION:
- *
- * The information in this document is subject to special
- * restrictions in a confidential disclosure agreement bertween
- * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
- * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
- * Sun's specific written approval. This documment and all copies
- * and derivative works thereof must be returned or destroyed at
- * Sun's request.
- *
- * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
- *
- *+ENOTICE
- */
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <pwd.h>
- #include <sys/socket.h>
- #include <ctype.h>
- #include <DtMail/DtMail.hh>
- #include <EUSDebug.hh>
- #include "DynamicLib.hh"
- #include <DtMail/Threads.hh>
- #include <DtMail/ImplDriver.hh>
- #include "ImplConfigTable.hh"
- #include "SigChldImpl.hh"
- #include <DtMail/IO.hh>
- #include <DtMail/Common.h>
- // For CHARSET
- //-------------------------------------
- // HACK ALERT
- // Any code change within "For CHARSET" should be changed in
- // RFCBodyPart and Session because the same methods are duplicated
- // in both of these classes.
- // See RFCImpl.hh or DtMail/DtMail.hh for more explanation.
- //-------------------------------------
- #include <locale.h>
- #include <time.h>
- #include <DtHelp/LocaleXlate.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <limits.h>
- #include <ctype.h>
-
- #ifndef True
- #define True 1
- #endif
- #ifndef False
- #define False 0
- #endif
-
- #if defined(SunOS) && (SunOS < 55)
- extern "C" {
- #endif
- #include <iconv.h>
- #if defined(SunOS) && (SunOS < 55)
- }
- #endif
- //End of CHARSET
- DtVirtArray<SigChldInfo *> *DtMailSigChldList;
- void * _DtMutex;
- static const int SessionSignature = 0xef9421cc;
- static const int MaxImpls = 16;
- static const int MAXIMUM_PATH_LENGTH = 2048;
- DtMail::Session::Session(DtMailEnv & error, const char * app_name)
- : _events(16), _valid_keys(2048)
- {
- _DtMutex = MutexInit();
- error.clear();
- _object_signature = 0;
- _cur_key = 0;
- // Create the ToolTalk session for managing file locking,
- // if one doesn't exist.
- _tt_channel = tt_default_procid();
- if (tt_pointer_error(_tt_channel) != TT_OK) {
- _tt_channel = ttdt_open(&_tt_fd, app_name, "SunSoft", "%I", 0);
- if (tt_pointer_error(_tt_channel) != TT_OK) {
- error.setError(DTME_TTFailure);
- DebugPrintf(1,
- "DtMail::createSession - ttdt_open returns %s\n",
- tt_status_message(tt_pointer_error(_tt_channel)));
- return;
- }
- }
- else {
- _tt_fd = tt_fd();
- }
- // The event_fd is how we allow async behavior to occur in a
- // compatible way. We use a Unix domain socket as the file descriptor.
- // The client will watch for activity on this file descriptor, and
- // call our event routine when there is activity (either from XtMainLoop,
- // or through some other method).
- //
- pipe(_event_fd);
- _app_name = strdup(app_name);
- DtMailEnv b_error;
- _mail_rc = new MailRc(error, this);
- buildImplTable(error);
- if (error.isSet()) {
- return;
- }
- _obj_mutex = MutexInit();
- // The default implementation is specified via the DEFAULT_BACKEND
- // variable. If this is not set in the .mailrc, then choose entry
- // zero.
- //
- const char * value;
- _mail_rc->getValue(b_error, "DEFAULT_BACKEND", &value);
- if (b_error.isNotSet()) {
- _default_impl = lookupImpl(value);
- if (_default_impl < 0) {
- _default_impl = 0;
- }
- }
- else {
- b_error.clear();
- _default_impl = 0;
- }
- DtMailSigChldList = new DtVirtArray<SigChldInfo *>(8);
- _busy_cb = NULL;
- _busy_cb_data = NULL;
- _canAutoSave = DTM_TRUE;
- _object_signature = SessionSignature;
- return;
- }
- DtMail::Session::~Session(void)
- {
- if (_object_signature != SessionSignature) { // Been here, did that!
- return;
- }
-
- {
- MutexLock lock_scope(_obj_mutex);
-
- _object_signature = 0;
-
- ttdt_close(_tt_channel, NULL, 1);
-
- DtMailEnv b_error;
-
- // Close off the dynamic libraries and free the impl table.
- for (int tbl = 0; tbl < _num_impls; tbl++) {
- free(_impls[tbl].impl_name);
- DynamicLib * dl = (DynamicLib *)_impls[tbl].impl_lib;
- delete dl;
- }
- free(_impls);
- lock_scope.unlock_and_destroy();
- delete _mail_rc;
- close(_event_fd[0]);
- close(_event_fd[1]);
- }
-
- }
- const char **
- DtMail::Session::enumerateImpls(DtMailEnv & error)
- {
- error.clear();
- return(_impl_names);
- }
- void
- DtMail::Session::setDefaultImpl(DtMailEnv & error, const char * impl)
- {
- int slot = lookupImpl(impl);
- if (slot < 0) {
- error.setError(DTME_NoSuchImplementation);
- return;
- }
- MutexLock lock_scope(_obj_mutex);
- _default_impl = slot;
- error.clear();
- }
- const char *
- DtMail::Session::getDefaultImpl(DtMailEnv & error)
- {
- if (_num_impls == 0) {
- error.setError(DTME_NoImplementations);
- return(NULL);
- }
- error.clear();
- return(_impl_names[_default_impl]);
- }
- void
- DtMail::Session::queryImpl(DtMailEnv & error,
- const char * impl,
- const char * capability,
- ...)
- {
- va_list args;
- va_start(args, capability);
- queryImplV(error, impl, capability, args);
- va_end(args);
- return;
- }
- void
- DtMail::Session::queryImplV(DtMailEnv & error,
- const char * impl,
- const char * capability,
- va_list args)
- {
- int slot = lookupImpl(impl);
- if (slot < 0) {
- error.setError(DTME_NoSuchImplementation);
- return;
- }
- error.clear();
- // We need to retrieve the QueryImpl entry point for the implementation.
- //
- QueryImplEntry qie;
-
- qie = (QueryImplEntry)_impls[slot].impl_meta_factory(QueryImplEntryOp);
- if (!qie) {
- error.setError(DTME_ImplFailure);
- return;
- }
- qie(*this, error, capability, args);
- return;
- }
- DtMail::MailBox *
- DtMail::Session::mailBoxConstruct(DtMailEnv & error,
- DtMailObjectSpace space,
- void * arg,
- DtMailCallback open_callback,
- void * client_data,
- const char * impl_name)
- {
- // If the client specified an implementation of choice, then that
- // is the only thing we use.
- //
- int primary_impl = _default_impl;
- if (impl_name) {
- int sl = lookupImpl(impl_name);
- if (sl < 0) {
- error.setError(DTME_NoSuchImplementation);
- return(NULL);
- }
- primary_impl = sl;
- }
- // First thing we will do is see if the default implementation
- // can open this file. If so, then we will create a mail box object
- // based on the default implementation.
- //
- int const_impl;
- QueryOpenEntry qoe;
-
- qoe = (QueryOpenEntry)
- _impls[primary_impl].impl_meta_factory(QueryOpenEntryOp);
- if (!qoe) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- if (qoe(*this, error, space, arg) == DTM_FALSE) {
- // Don't go on if the client specified an implementation.
- //
- if (impl_name) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- // Oh well, let's walk through the list of impls and see if any of
- // them will take ownership of this file.
- //
- MutexLock lock_scope(_obj_mutex);
- const_impl = -1;
- for(int slot = 0; slot < _num_impls; slot++) {
- qoe = (QueryOpenEntry)
- _impls[slot].impl_meta_factory(QueryOpenEntryOp);
- if (!qoe) {
- // Just skip this implementation.
- continue;
- }
- if (qoe(*this, error, space, arg) == DTM_TRUE) {
- const_impl = slot;
- break;
- }
- }
- // If we didn't find an impl, then we have to give up.
- //
- if (const_impl < 0) {
- error.setError(DTME_NotMailBox);
- return(NULL);
- }
- }
- else {
- const_impl = primary_impl;
- }
- // At this point we have an implementation that is willing to work
- // with the path. Get its mail box constructor and build a mailbox
- // from it.
- //
- MailBoxConstructEntry mbce;
-
- mbce = (MailBoxConstructEntry)
- _impls[const_impl].impl_meta_factory(MailBoxConstructEntryOp);
- if (!mbce) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- return(mbce(*this, error, space, arg, open_callback, client_data));
- }
- DtMail::Message *
- DtMail::Session::messageConstruct(DtMailEnv & error,
- DtMailObjectSpace space,
- void * arg,
- DtMailCallback open_callback,
- void * client_data,
- const char * impl_name)
- {
- // If the client specified an implementation of choice, then that
- // is the only thing we use.
- //
- int primary_impl = _default_impl;
- if (impl_name) {
- int sl = lookupImpl(impl_name);
- if (sl < 0) {
- error.setError(DTME_NoSuchImplementation);
- return(NULL);
- }
- primary_impl = sl;
- }
- int const_impl;
- QueryMessageEntry qoe;
-
- qoe = (QueryMessageEntry)
- _impls[primary_impl].impl_meta_factory(QueryMessageEntryOp);
- if (!qoe) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- if (qoe(*this, error, space, arg) == DTM_FALSE) {
- // Don't go on if the client specified an implementation.
- //
- if (impl_name) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- // Oh well, let's walk through the list of impls and see if any of
- // them will take ownership of this file.
- //
- MutexLock lock_scope(_obj_mutex);
- const_impl = -1;
- for(int slot = 0; slot < _num_impls; slot++) {
- qoe = (QueryMessageEntry)
- _impls[slot].impl_meta_factory(QueryMessageEntryOp);
- if (!qoe) {
- // Just skip this implementation.
- continue;
- }
- if (qoe(*this, error, space, arg) == DTM_TRUE) {
- const_impl = slot;
- break;
- }
- }
- // If we didn't find an impl, then we have to give up.
- //
- if (const_impl < 0) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- }
- else {
- const_impl = primary_impl;
- }
- // At this point we have an implementation that is willing to work
- // with the path. Get its mail box constructor and build a mailbox
- // from it.
- //
- MessageConstructEntry mbce;
-
- mbce = (MessageConstructEntry)
- _impls[const_impl].impl_meta_factory(MessageConstructEntryOp);
- if (!mbce) {
- error.setError(DTME_ImplFailure);
- return(NULL);
- }
- return(mbce(*this, error, space, arg, open_callback, client_data));
- }
- DtMail::Transport *
- DtMail::Session::transportConstruct(DtMailEnv & error,
- const char * impl,
- DtMailStatusCallback call_back,
- void * client_data)
- {
- // We need to find the implementation for starters.
- //
- int slot = lookupImpl(impl);
- if (slot < 0) {
- error.setError(DTME_NoSuchImplementation);
- return(NULL);
- }
- TransportConstructEntry tce;
- tce = (TransportConstructEntry)
- _impls[slot].impl_meta_factory(TransportConstructEntryOp);
- if (!tce) {
- error.setError(DTME_NotSupported);
- return(NULL);
- }
- return(tce(*this, error, call_back, client_data));
- }
- DtMail::MailRc *
- DtMail::Session::mailRc(DtMailEnv & error)
- {
- error.clear();
- return(_mail_rc);
- }
- //
- // NEEDS TO BE DELETED .. SHOULD NO LONGER BE USED...
- //
- void
- DtMail::Session::setError(DtMailEnv & error, const DTMailError_t minor_code)
- {
- error.setError(minor_code);
- //DtMail::setError(*this, error, minor_code);
- }
- DtMailBoolean
- DtMail::Session::pollRequired(DtMailEnv & error)
- {
- error.clear();
- #if defined(POSIX_THREADS)
- return(DTM_FALSE);
- #else
- return(DTM_TRUE);
- #endif
- }
- int
- DtMail::Session::eventFileDesc(DtMailEnv & error)
- {
- error.clear();
- return(_event_fd[0]);
- }
- void
- DtMail::Session::poll(DtMailEnv & error)
- {
- error.clear();
- #if defined(POSIX_THREADS)
- return; // A thread does this job.
- #else
- // We will grab the time and determine what needs to run.
- // Any events that have expired since the last time we were
- // called are automatically ran. If the event returns DTM_TRUE,
- // then reset last_ran to the current time to cause the event
- // to not run for the full wait interval; otherwise, refrain
- // and let the event happen again at the next poll interval
- //
- time_t now = time(NULL);
- for (int ev = 0; ev < _events.length(); ev++) {
- EventRoutine * event = _events[ev];
- if ((now - event->last_ran) > event->interval) {
- if (event->routine(event->client_data) == DTM_TRUE)
- event->last_ran = now;
- }
- }
- return;
- #endif
- }
- char *
- DtMail::Session::expandPath(DtMailEnv & error, const char * path)
- {
- const char * fold_path;
- if (path == NULL) {
- error.setError(DTME_BadArg);
- return(NULL);
- }
- error.clear();
- char * exp_name = (char *)malloc(MAXIMUM_PATH_LENGTH);
- if (exp_name == NULL) {
- error.setError(DTME_NoMemory);
- return(NULL);
- }
- if (strchr(path, '$') != NULL) {
- sprintf (exp_name, "echo %s", path);
- FILE *fp;
- if ((fp = popen(exp_name, "r")) != NULL) {
- exp_name[0] = '\0';
- if (fgets(exp_name, MAXIMUM_PATH_LENGTH, fp) != NULL &&
- exp_name[0] != '\0')
- // get rid of \n at end of string
- exp_name[strlen(exp_name)-1] = '\0';
- else
- strcpy(exp_name, path);
- pclose(fp);
- }
- else
- strcpy(exp_name, path);
- }
- else
- strcpy(exp_name, path);
- char * exp_name2 = (char *)malloc(MAXIMUM_PATH_LENGTH);
- exp_name2[0] = '\0';
- switch (exp_name[0]) {
- case '+':
- // This is relative to the folder path. Figure out what that is.
- {
- _mail_rc->getValue(error, "folder", &fold_path);
- if (error.isNotSet()) {
- if (*fold_path != '/' && *fold_path != '.' &&
- *fold_path != '~' && *fold_path != '$')
- strcpy(exp_name2, "~/");
- strcat(exp_name2, fold_path);
- strcat(exp_name2, "/");
- }
- else // Use the default folder
- strcpy(exp_name2, "~/");
-
- strcat(exp_name2, &exp_name[1]);
-
- // We need to call ourselves again to deal with
- // relative paths in the folder directory.
- //
- char * old_exp = exp_name2;
- exp_name2 = expandPath(error, old_exp);
- free(old_exp);
- break;
- }
-
- case '~':
- // This is relative to the user's home directory.
- {
- passwd pw;
- const char * start;
- if (exp_name[1] == '/' || exp_name[1] == '\0') {
- GetPasswordEntry(pw);
- start = &exp_name[1];
- }
- else {
- passwd * pw_p;
- char * slash = strchr(&exp_name[1], '/');
- if (slash == NULL) {
- error.clear();
- error.setError(DTME_NoSuchFile);
- break;
- }
- int len = slash - &exp_name[1];
- char * name = new char[len + 1];
- strncpy(name, &exp_name[1], len);
- name[len] = 0;
- pw_p = getpwnam(name);
- if (!pw_p) {
- error.clear();
- error.setError(DTME_NoSuchFile);
- break;
- }
- pw = *pw_p;
- delete [] name;
- start = slash;
- }
- strcpy(exp_name2, pw.pw_dir);
- strcat(exp_name2, start);
- break;
- }
- // We have a directory or no specials. Just copy the path and
- // return.
- case '.':
- case '/':
- default:
- strcpy(exp_name2, exp_name);
- break;
- }
- free(exp_name);
- return(exp_name2);
- }
- // This routine takes a path and checks to see if the path can be
- // expressed relative to the "folder" path. If it can, it returns
- // the relative path; otherwise, it returns the original path.
- char *
- DtMail::Session::getRelativePath(DtMailEnv & error, const char * path)
- {
- const char * fold_path;
- if (path == NULL) {
- error.setError(DTME_BadArg);
- return(NULL);
- }
- error.clear();
- char * exp_name = (char *)malloc(MAXIMUM_PATH_LENGTH);
- if (!exp_name) {
- error.setError(DTME_NoMemory);
- return(NULL);
- }
- exp_name[0] = '\0'; // Just for errors.
- switch (path[0]) {
- case '/':
- // This is an absolute path, so there is a chance that
- // we can trim it down to a relative path if it goes down
- // the same way as the folder path.
- {
- _mail_rc->getValue(error, "folder", &fold_path);
- if (error.isNotSet()) {
- strcpy(exp_name, fold_path);
-
- // We need to call ourselves again to deal with
- // relative paths in the folder directory.
- //
- char * old_exp = exp_name;
- exp_name = expandPath(error, old_exp);
- free(old_exp);
- // Check to see if the path starts with the folder path.
- char * matched_path = const_cast<char *>(strstr(path, exp_name));
- if (matched_path == path) {
- // Yes it does, make it a relative path to the folder dir.
- int folder_path_length = strlen(exp_name);
- while (path[folder_path_length] == '/')
- folder_path_length++;
- strcpy(exp_name, &path[folder_path_length]);
- break;
- } else {
- strcpy(exp_name, path);
- break;
- }
- }
- else {
- // There is no folder variable so just fall through to the
- // default.
- error.clear();
- }
- }
- case '+':
- // This is relative to the folder path. Leave it alone.
- // The only time we are likely to see a leading '+' is
- // when the path was carried over from mailtool in the .mailrc.
- case '~':
- // This is relative to the user's home directory. Leave it alone.
- // The only time we are likely to see a leading '~' is
- // when the path was carried over from mailtool in the .mailrc.
- case '.':
- // This is relative to the current directory where dtmail is
- // running. Leave it alone. The only time we are likely to see
- // a leading '.' is when the path was carried over from mailtool
- // in the .mailrc.
- default:
- {
- strcpy(exp_name, path);
- break;
- }
- }
- return(exp_name);
- }
- void
- DtMail::Session::addEventRoutine(DtMailEnv & error,
- DtMailEventFunc routine,
- void * client_data,
- time_t interval)
- {
- error.clear();
- EventRoutine * er = new EventRoutine;
- er->routine = routine;
- er->client_data = client_data;
- er->interval = interval;
- er->last_ran = 0; // This will case this routine to run immediately.
- _events.append(er);
- }
- void
- DtMail::Session::removeEventRoutine(DtMailEnv & error,
- DtMailEventFunc routine,
- void * client_data)
- {
- error.clear();
- for (int slot = 0; slot < _events.length(); slot++) {
- EventRoutine * event = _events[slot];
- if (event->routine == routine &&
- event->client_data == client_data) {
- delete event;
- _events.remove(slot);
- }
- }
- }
- void
- DtMail::Session::writeEventData(DtMailEnv&,
- const void * buf,
- const unsigned long size)
- {
- int status = SafeWrite(_event_fd[1], buf, (int)size);
- }
- DtMailBoolean
- DtMail::Session::validObjectKey(DtMailObjectKey key)
- {
- return(_valid_keys.indexof(key) < 0 ? DTM_FALSE : DTM_TRUE);
- }
- DtMailObjectKey
- DtMail::Session::newObjectKey(void)
- {
- MutexLock lock_scope(_obj_mutex);
- _cur_key += 1;
- _valid_keys.append(_cur_key);
- return(_cur_key);
- }
- void
- DtMail::Session::removeObjectKey(DtMailObjectKey key)
- {
- MutexLock lock_scope(_obj_mutex);
- int slot = _valid_keys.indexof(key);
- if (slot >= 0) {
- _valid_keys.remove(slot);
- }
- }
- void
- DtMail::Session::registerDisableGroupPrivilegesCallback(
- DisableGroupPrivilegesCallback cb,
- void * cb_data)
- {
- _disableGroupPrivileges_cb = cb;
- _disableGroupPrivileges_cb_data = cb_data;
- }
- #ifdef DEAD_WOOD
- void
- DtMail::Session::unregisterDisableGroupPrivilegesCallback(void)
- {
- _disableGroupPrivileges_cb = NULL;
- _disableGroupPrivileges_cb_data = NULL;
- }
- #endif /* DEAD_WOOD */
- void
- DtMail::Session::disableGroupPrivileges(void)
- {
- if (_disableGroupPrivileges_cb) {
- _disableGroupPrivileges_cb(_disableGroupPrivileges_cb_data);
- }
- }
- void
- DtMail::Session::registerEnableGroupPrivilegesCallback(
- EnableGroupPrivilegesCallback cb,
- void * cb_data)
- {
- _enableGroupPrivileges_cb = cb;
- _enableGroupPrivileges_cb_data = cb_data;
- }
- #ifdef DEAD_WOOD
- void
- DtMail::Session::unregisterEnableGroupPrivilegesCallback(void)
- {
- _enableGroupPrivileges_cb = NULL;
- _enableGroupPrivileges_cb_data = NULL;
- }
- #endif /* DEAD_WOOD */
- void
- DtMail::Session::enableGroupPrivileges(void)
- {
- if (_enableGroupPrivileges_cb) {
- _enableGroupPrivileges_cb(_enableGroupPrivileges_cb_data);
- }
- }
- void
- DtMail::Session::registerBusyCallback(DtMailEnv&,
- BusyApplicationCallback cb,
- void * cb_data)
- {
- _busy_cb = cb;
- _busy_cb_data = cb_data;
- }
- #ifdef DEAD_WOOD
- void
- DtMail::Session::unregisterBusyCallback(DtMailEnv & error)
- {
- _busy_cb = NULL;
- _busy_cb_data = NULL;
- }
- #endif /* DEAD_WOOD */
- void
- DtMail::Session::setBusyState(DtMailEnv &error, DtMailBusyState busy_state)
- {
- if (_busy_cb) {
- _busy_cb(error, busy_state, _busy_cb_data);
- }
- }
- void
- DtMail::Session::registerLastInteractiveEventTimeCallback(
- LastInteractiveEventTimeCallback cb,
- void * cb_data)
- {
- _interactive_time_cb = cb;
- _interactive_time_cb_data = cb_data;
- }
- long
- DtMail::Session::lastInteractiveEventTime(void)
- {
- if (_interactive_time_cb) {
- return(_interactive_time_cb(_interactive_time_cb_data));
- }
- else
- return(0);
- }
- void
- DtMail::Session::buildImplTable(DtMailEnv & error)
- {
- error.clear();
- // Let's pick a ridiculous number of implementations.
- _impls = (Impls *)malloc(sizeof(Impls) * MaxImpls);
- _impl_names = (const char **)malloc(sizeof(char *) * (MaxImpls + 1));
- // We will simply walk through the default implementations
- // to start, adding them to the impl table.
- int tbl;
- for (tbl = 0, _num_impls = 0; initial_impls[tbl].meta_entry_point; tbl++) {
- // Get the library handle.
- DynamicLib * dl = CreatePlatformDl(initial_impls[tbl].lib_name);
- if (dl) { // We are only interested in libraries we can load.
- _impls[_num_impls].impl_lib = dl;
- _impls[_num_impls].impl_meta_factory =
- (MetaImplFactory)dl->getSym(initial_impls[tbl].meta_entry_point);
- if (_impls[_num_impls].impl_meta_factory == NULL) {
- delete dl;
- continue;
- }
- _impls[_num_impls].impl_name = strdup(initial_impls[tbl].impl_name);
- _impl_names[_num_impls] = _impls[_num_impls].impl_name;
- _num_impls += 1;
- }
- }
- _impl_names[_num_impls] = NULL;
- if (_num_impls == 0) {
- error.setError(DTME_NoImplementations);
- }
- }
- int
- DtMail::Session::lookupImpl(const char * impl)
- {
- MutexLock lock_scope(_obj_mutex);
- for(int i = 0; i < _num_impls; i++) {
- if (strcmp(_impls[i].impl_name, impl) == 0) {
- return(i);
- }
- }
- return(-1);
- }
- void
- DtMail::Session::setAutoSaveFlag(
- DtMailBoolean flag
- )
- {
- _canAutoSave = flag;
- }
- DtMailBoolean
- DtMail::Session::getAutoSaveFlag()
- {
- return(_canAutoSave);
- }
- extern "C" void
- ChildExitNotify(const int pid, const int status)
- {
- // We need to lookup the child, and set the status of the
- // correct condition variable. We will remove the slot, but
- // the thread will destroy the buffer in the slot.
- //
- for (int slot = 0; slot < DtMailSigChldList->length(); slot++) {
- if ((*DtMailSigChldList)[slot]->pid == pid) {
- (*DtMailSigChldList)[slot]->cond = status;
- DtMailSigChldList->remove(slot);
- return;
- }
- }
- // Not finding the pid is not a problem. Just means it wasn't
- // one of ours.
- //
- return;
- }
- // For CHARSET
- /*
- * Wrapper functions taken from libHelp/CEUtil.c
- *
- * We took these functions and renamed them because
- * 1. Originally these are called _DtHelpCeXlate* and thus they are private
- * to libHelp and not exported to outside of libHelp.
- * 2. When these functions are moved to another library, then users of these
- * functions would only need to link with a different library. The caller
- * doesn't have to modify code.
- */
- static const char *DfltStdCharset = "us-ascii";
- static const char *DfltStdLang = "C";
- static char MyPlatform[_DtPLATFORM_MAX_LEN+1];
- static _DtXlateDb MyDb = NULL;
- static char MyProcess = False;
- static char MyFirst = True;
- static int ExecVer;
- static int CompVer;
- /******************************************************************************
- * Function: static int OpenLcxDb ()
- *
- * Parameters: none
- *
- * Return Value: 0: ok
- * -1: error
- *
- * errno Values:
- *
- * Purpose: Opens the Ce-private Lcx database
- *
- *****************************************************************************/
- int
- DtMail::Session::OpenLcxDb (void)
- {
- time_t time1 = 0;
- time_t time2 = 0;
- while (MyProcess == True)
- {
- /* if time out, return */
- if (time(&time2) == (time_t)-1)
- return -1;
- if (time1 == 0)
- time1 = time2;
- else if (time2 - time1 >= (time_t)30)
- return -1;
- }
- if (MyFirst == True)
- {
- MyProcess = True;
- if (_DtLcxOpenAllDbs(&MyDb) == 0 &&
- _DtXlateGetXlateEnv(MyDb,MyPlatform,&ExecVer,&CompVer) != 0)
- {
- _DtLcxCloseDb(&MyDb);
- MyDb = NULL;
- }
- MyFirst = False;
- MyProcess = False;
- }
- return (MyDb == NULL ? -1 : 0 );
- }
- /******************************************************************************
- * Function: int DtXlateOpToStdLocale(char *operation, char *opLocale,
- * char **ret_stdLocale,
- * char **ret_stdLang,
- * char **ret_stdSet)
- *
- * Parameters:
- * operation Operation associated with the locale value
- * opLocale An operation-specific locale string
- * ret_locale Returns the std locale
- * Caller must free this string.
- * ret_stdLang Returns the std language & territory string.
- * Caller must free this string.
- * ret_stdSet Returns the std code set string.
- * Caller must free this string.
- *
- * Return Value:
- *
- * Purpose: Gets the standard locale given an operation and its locale
- *
- *****************************************************************************/
- void
- DtMail::Session::DtXlateOpToStdLocale (
- char *operation,
- char *opLocale,
- char **ret_stdLocale,
- char **ret_stdLang,
- char **ret_stdSet)
- {
- int result = OpenLcxDb();
- if (result == 0) {
- (void) _DtLcxXlateOpToStd(
- MyDb, MyPlatform, CompVer,
- operation, opLocale,
- ret_stdLocale, ret_stdLang, ret_stdSet, NULL);
- }
- /* if failed, give default values */
- if (ret_stdLocale != NULL && (result != 0 || *ret_stdLocale == NULL))
- {
- *ret_stdLocale =
- (char *)malloc(strlen(DfltStdLang)+strlen(DfltStdCharset)+3);
- sprintf(*ret_stdLocale,"%s.%s",DfltStdLang,DfltStdCharset);
- }
- if (ret_stdLang != NULL && (result != 0 || *ret_stdLang == NULL))
- *ret_stdLang = (char *)strdup(DfltStdLang);
- if (ret_stdSet != NULL && (result != 0 || *ret_stdSet == NULL))
- *ret_stdSet = (char *)strdup(DfltStdCharset);
- }
- /******************************************************************************
- * Function: int DtXlateStdToOpLocale(char *operation,
- * char *stdLocale,
- * char *dflt_opLocale,
- * char **ret_opLocale)
- *
- * Parameters:
- * operation operation whose locale value will be retrieved
- * stdLocale standard locale value
- * dflt_opLocale operation-specific locale-value
- * This is the default value used in error case
- * ret_opLocale operation-specific locale-value placed here
- * Caller must free this string.
- *
- * Return Value:
- *
- * Purpose: Gets an operation-specific locale string given the standard string
- *
- *****************************************************************************/
- void
- DtMail::Session::DtXlateStdToOpLocale (
- char *operation,
- char *stdLocale,
- char *dflt_opLocale,
- char **ret_opLocale)
- {
- int result = this->OpenLcxDb();
- if (ret_opLocale)
- *ret_opLocale = NULL;
- if (result == 0) {
- (void) _DtLcxXlateStdToOp(
- MyDb, MyPlatform, CompVer,
- operation, stdLocale,
- NULL, NULL, NULL,
- ret_opLocale);
- }
- /* if translation fails, use a default value */
- if (ret_opLocale && (result != 0 || *ret_opLocale == NULL))
- {
- if (dflt_opLocale) *ret_opLocale = (char *)strdup(dflt_opLocale);
- else if (stdLocale) *ret_opLocale = (char *)strdup(stdLocale);
- }
- }
- /******************************************************************************
- * Function: int DtXlateStdToOpCodeset (
- * char *operation,
- * char *stdCodeset,
- * char *dflt_opCodeset,
- * char **ret_opCodeset)
- *
- * Parameters:
- * operation operation whose codeset value will be retrieved
- * stdCodeset standard codeset value
- * dflt_opCodeset operation-specific codeset-value
- * This is the default value used in error case
- * ret_opCodeset operation-specific codeset-value placed here
- * Caller must free this string.
- *
- * Return Value:
- *
- * Purpose: Gets an operation-specific locale string given the standard string
- *
- *****************************************************************************/
- void
- DtMail::Session::DtXlateStdToOpCodeset (
- char *operation,
- char *stdCodeset,
- char *dflt_opCodeset,
- char **ret_opCodeset)
- {
- int result = this->OpenLcxDb();
- if (ret_opCodeset)
- *ret_opCodeset = NULL;
- if (result == 0)
- {
- (void) _DtLcxXlateStdToOp(
- MyDb, MyPlatform, CompVer,
- operation,
- NULL, NULL, stdCodeset, NULL,
- ret_opCodeset);
- }
- /* if translation fails, use a default value */
- if (ret_opCodeset && (result != 0 || *ret_opCodeset == NULL))
- {
- if (dflt_opCodeset) *ret_opCodeset = (char *)strdup(dflt_opCodeset);
- else if (stdCodeset) *ret_opCodeset = (char *)strdup(stdCodeset);
- }
- }
- void
- DtMail::Session::DtXlateMimeToIconv(
- const char *mimeId,
- const char *defaultCommonCS,
- const char *defaultIconvCS,
- char **ret_commonCS,
- char **ret_platformIconv)
- {
- int exists = -1;
- this->OpenLcxDb();
-
- exists = _DtLcxXlateOpToStd(
- MyDb, MyPlatform, CompVer,
- DtLCX_OPER_MIME, mimeId,
- NULL, NULL, ret_commonCS, NULL);
- if (exists == -1)
- {
- exists = _DtLcxXlateOpToStd(
- MyDb, "CDE", 0,
- DtLCX_OPER_MIME, mimeId,
- NULL, NULL, ret_commonCS, NULL);
- if (exists == -1)
- *ret_commonCS = (char *)strdup(defaultCommonCS);
- }
- exists = _DtLcxXlateStdToOp(
- MyDb, MyPlatform, CompVer,
- DtLCX_OPER_ICONV3,
- NULL, NULL, *ret_commonCS, NULL,
- ret_platformIconv);
- if (exists == -1)
- *ret_platformIconv = (char *)strdup(defaultIconvCS);
- }
- void
- DtMail::Session::DtXlateLocaleToMime(
- const char * locale,
- const char * defaultCommonCS,
- const char * defaultMimeCS,
- char ** ret_mimeCS)
- {
- char * commonCS = NULL;
- this->OpenLcxDb();
- /* look for platform-specific locale to CDE translation */
- _DtLcxXlateOpToStd(
- MyDb, MyPlatform, CompVer,
- DtLCX_OPER_SETLOCALE, locale,
- NULL, NULL, &commonCS, NULL);
- if (!commonCS)
- commonCS = (char *)strdup(defaultCommonCS);
- /* look for platform-specific MIME types; by default, there is none */
- _DtLcxXlateStdToOp(
- MyDb, MyPlatform, CompVer,
- DtLCX_OPER_MIME,
- NULL, NULL, commonCS, NULL,
- ret_mimeCS);
- if (!(*ret_mimeCS))
- {
- _DtLcxXlateStdToOp(
- MyDb, "CDE", 0,
- DtLCX_OPER_MIME,
- NULL, NULL, commonCS, NULL,
- ret_mimeCS);
- if (!(*ret_mimeCS))
- *ret_mimeCS = (char *)strdup(defaultMimeCS);
- }
- if (commonCS)
- free(commonCS);
- }
- // Return iconv name of the given codeset.
- // If iconv name does not exist, return NULL.
- char *
- DtMail::Session::csToConvName(char *cs)
- {
- int exists = -1;
- char *commonCS = NULL;
- char *convName = NULL;
- char *ret_target = NULL;
-
- this->OpenLcxDb();
-
- // Convert charset to upper case first because charset table is
- // case sensitive.
- if (cs)
- {
- int len_cs = strlen(cs);
- for ( int num_cs = 0; num_cs < len_cs; num_cs++ )
- *(cs+num_cs) = toupper(*(cs+num_cs));
- }
- exists = _DtLcxXlateOpToStd(
- MyDb, MyPlatform, CompVer,
- DtLCX_OPER_MIME, cs,
- NULL, NULL, &commonCS, NULL);
- if (exists == -1) {
- exists = _DtLcxXlateOpToStd(
- MyDb, "CDE", 0,
- DtLCX_OPER_MIME, cs,
- NULL, NULL, &commonCS, NULL);
- if (exists == -1)
- return NULL;
- }
-
- DtXlateStdToOpCodeset(DtLCX_OPER_INTERCHANGE_CODESET,
- commonCS,
- NULL,
- &ret_target);
- DtXlateStdToOpCodeset(DtLCX_OPER_ICONV3,
- ret_target,
- NULL,
- &convName);
- if ( ret_target )
- free( ret_target );
- if ( commonCS )
- free( commonCS );
-
- // Workaround for libDtHelp
- // Case of no iconv name for a particular locale, eg. C,
- // check for empty string.
- if ( convName != NULL )
- {
- if ( strlen(convName) > 0 )
- return convName;
- else
- free( convName );
- }
- return NULL;
- }
- // Return current locale's iconv name.
- char *
- DtMail::Session::locToConvName()
- {
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
-
- DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
- setlocale(LC_CTYPE, NULL),
- &ret_locale,
- &ret_lang,
- &ret_codeset);
- if (ret_codeset) {
- free(ret_codeset);
- ret_codeset = NULL;
- }
-
- if (ret_lang) {
- free(ret_lang);
- ret_lang = NULL;
- }
-
- DtXlateStdToOpLocale(DtLCX_OPER_ICONV3,
- ret_locale,
- NULL,
- &ret_codeset);
- if (ret_locale)
- free(ret_locale);
- // Workaround for libDtHelp
- // Case of no iconv name for a particular locale, eg. C,
- // check for empty string.
- if ( ret_codeset != NULL )
- {
- if ( strlen(ret_codeset) > 0 )
- return ret_codeset;
- else
- free(ret_codeset);
- }
- return NULL;
- }
- // Return target codeset's iconv name.
- char *
- DtMail::Session::targetConvName()
- {
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
- char *ret_target = NULL;
- char *ret_convName = NULL;
-
- DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
- setlocale(LC_CTYPE, NULL),
- &ret_locale,
- &ret_lang,
- &ret_codeset);
- DtXlateStdToOpLocale(DtLCX_OPER_INTERCHANGE_CODESET,
- ret_locale,
- NULL,
- &ret_target);
- // Or do I call csToConvName() here??
- DtXlateStdToOpCodeset(DtLCX_OPER_ICONV3,
- ret_target,
- NULL,
- &ret_convName);
-
- if (ret_locale)
- free(ret_locale);
- if (ret_lang)
- free(ret_lang);
- if (ret_codeset)
- free(ret_codeset);
- if (ret_target)
- free(ret_target);
- // Workaround for libDtHelp
- // Case of no iconv name for a particular locale, eg. C,
- // check for empty string.
- if ( ret_convName != NULL )
- {
- if ( strlen(ret_convName) > 0 )
- return ret_convName;
- else
- free(ret_convName);
- }
- return NULL;
- }
- // Return target codeset's MIME (tag) name.
- char *
- DtMail::Session::targetTagName()
- {
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
- char *ret_target = NULL;
- DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
- setlocale(LC_CTYPE, NULL),
- &ret_locale,
- &ret_lang,
- NULL);
- DtXlateStdToOpLocale(DtLCX_OPER_INTERCHANGE_CODESET,
- ret_locale,
- NULL,
- &ret_target);
- DtXlateStdToOpCodeset(DtLCX_OPER_MIME,
- ret_target,
- NULL,
- &ret_codeset);
- if (ret_locale)
- free(ret_locale);
- if (ret_lang)
- free(ret_lang);
- if (ret_target)
- free(ret_target);
- return ret_codeset;
- }
- // Given an extension to the interchange codeset name.
- // Return target codeset's MIME (tag) name.
- // The extension is for Sun V3 backward compatibility so that
- // reverse mapping of out-going charset tag is the same as
- // OpenWindows Mailtool.
- char *
- DtMail::Session::targetTagName(char *special)
- {
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
- char *ret_target = NULL;
-
- DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
- setlocale(LC_CTYPE, NULL),
- &ret_locale,
- &ret_lang,
- &ret_codeset);
-
- // Allocate two more bytes for "." and null terminator.
- char *special_locale;
- special_locale = (char *)calloc(
- strlen(ret_locale) + strlen(special) + 2,
- sizeof(char));
- sprintf(special_locale, "%s%s%s", ret_locale, ".", special);
-
- DtXlateStdToOpLocale(DtLCX_OPER_INTERCHANGE_CODESET,
- special_locale,
- NULL,
- &ret_target);
- DtXlateStdToOpCodeset(DtLCX_OPER_MIME,
- ret_target,
- NULL,
- &ret_codeset);
-
- free(ret_locale);
- if (ret_lang)
- free(ret_lang);
- if (ret_target)
- free(ret_target);
- return ret_codeset;
- }
- // Given a message text and codesets
- // Convert message text from one codeset to another
- // Return 1 if conversion is successful else return 0.
- int
- DtMail::Session::csConvert(char **bp, unsigned long &bp_len, int free_bp,
- char *from_cs, char *to_cs)
- {
- DtMailEnv error;
- iconv_t cd;
- size_t ileft = (size_t) bp_len, oleft = (size_t) bp_len, ret = 0;
- #if defined(_AIX) || defined(sun) || defined(CSRG_BASED)
- const char *ip = (const char *) *bp;
- #else
- char *ip = *bp;
- #endif
- char *op = NULL;
- char *op_start = NULL;
- int mb_ret = 0;
- size_t delta;
- if ( *bp == NULL || **bp == '\0' || bp_len <= 0 )
- return 0;
- if ( to_cs == NULL || from_cs == NULL )
- return 0;
- if ( (cd = iconv_open(to_cs, from_cs)) == (iconv_t) -1 ) {
- switch (errno) {
- case EINVAL:
- error.logError(DTM_FALSE,
- "DtMail: Conversion from %s to %s is not supported.\n",
- from_cs, to_cs);
- break;
- } // end of switch statement
- return 0;
- }
- // Caller will set _must_free_body to DTM_TRUE if this routine
- // succeeds. Then this space will be freed appropriately.
- // Add 1 to buffer size for null terminator.
- op_start = op = (char *)calloc((unsigned int) bp_len + 1, sizeof(char));
- // When ileft finally reaches 0, the conversion still might not be
- // complete. Here's why we also need to check for E2BIG: Let's
- // say we're converting from eucJP to ISO-2022-JP, and there's just
- // enough room in the output buffer for the last input character,
- // but not enough room for the trailing "ESC ( B" (for switching
- // back to ASCII). In that case, iconv() will convert the last
- // input character, decrement ileft to zero, and then set errno to
- // E2BIG to tell us that it still needs more room for the "ESC ( B".
- errno = 0;
- while ( ileft > 0 || errno == E2BIG ) {
- errno = 0;
- if ((ret = iconv(cd, &ip, &ileft, &op, &oleft)) == (size_t) -1) {
- switch (errno) {
- case E2BIG: // increase output buffer size
- delta = ileft ? ileft : 3;
- bp_len += delta;
- op_start = (char *)realloc(
- (char *)op_start,
- (unsigned int) bp_len + 1);
- op = op_start + bp_len - delta - oleft;
- oleft += delta;
- // realloc does not clear out unused space.
- // Therefore, garbage shows up in output buffer.
- memset(op, 0, oleft + 1);
- break;
- case EILSEQ: // input byte does not belong to input codeset
- case EINVAL: // invalid input
- mb_ret = mblen(ip, MB_LEN_MAX);
- if ( (mb_ret > 0) && (oleft >= mb_ret) ) {
- strncat(op_start, ip, mb_ret);
- ip += mb_ret;
- op += mb_ret;
- oleft -= mb_ret;
- ileft -= mb_ret;
- mb_ret = 0;
- } else {
- // mb_ret is either 0 or -1 at this point,
- // then skip one byte
- // and try conversion again.
- ip++;
- ileft--;
- }
- break;
- case EBADF: // bad conversion descriptor
- break;
- } // end of switch statement
- }
- } // end of while loop
- iconv_close(cd);
- // Is this necessary?? Is _body_decode_len == strlen(_body)??
- // Or can _body_decode_len contain spaces??
- // Check to see if a body had been allocated by prior decoding.
- if (free_bp) {
- free(*bp);
- }
- *bp = op_start;
- bp_len = strlen(*bp);
- return 1;
- }
- // End of For CHARSET
|