1 line
85 KiB
C
Executable File
1 line
85 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
|
the limitations in the disclaimer below) provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
|
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE. */
|
|
|
|
#include "ph.h"
|
|
#define FILE_NUM 29
|
|
/* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
|
|
/**********************************************************************
|
|
* handling the Ph panel
|
|
**********************************************************************/
|
|
|
|
#pragma segment Ph
|
|
|
|
/************************************************************************
|
|
* the structure for the ph window
|
|
************************************************************************/
|
|
typedef struct UserEntryStruct *UserEntryPtr, **UserEntryHandle;
|
|
typedef struct UserEntryStruct
|
|
{
|
|
Str255 address;
|
|
Str63 name;
|
|
long start;
|
|
long end;
|
|
UHandle **fields;
|
|
UserEntryHandle next;
|
|
} UserEntry;
|
|
|
|
enum {
|
|
phcOkButton=0,
|
|
phcListButton,
|
|
phcFingerButton,
|
|
phcToButton,
|
|
phcCcButton,
|
|
phcBccButton,
|
|
phcInControl,
|
|
phcOutControl,
|
|
phcLimit
|
|
};
|
|
|
|
static short PhCntlIds[] = {PH_CNTL,PH_SERVER_CNTL,FINGER_CNTL,MAKE_TO_CNTL,MAKE_TO_CNTL,MAKE_TO_CNTL,PH_XLIN_CNTL,PH_XLOUT_CNTL};
|
|
|
|
typedef struct
|
|
{
|
|
PETEHandle qPTE;
|
|
PETEHandle aPTE;
|
|
Rect qRect;
|
|
Rect aRect;
|
|
ControlHandle controls[phcLimit];
|
|
Str255 label;
|
|
Str255 fingerServer;
|
|
DirSvcLookupType dirSvcType;
|
|
Str255 dirSvcServer;
|
|
long dirSvcPort;
|
|
Boolean dirSvcHostResolved;
|
|
Str255 ldapBaseObject;
|
|
short ldapSearchScope;
|
|
LDAPAttrListHdl ldapAttrList;
|
|
short fallback;
|
|
AAHandle siteinfo;
|
|
MyWindowPtr win;
|
|
UserEntryHandle userList;
|
|
short outlined;
|
|
Boolean selfURL;
|
|
Boolean live;
|
|
long queryTicks;
|
|
long dirtyTicks;
|
|
long lastDirty;
|
|
TransStream phStream;
|
|
} PhType, *PhPtr, **PhHandle;
|
|
PhHandle PhGlobals; /* for the ph window */
|
|
#define QPTE (*PhGlobals)->qPTE
|
|
#define APTE (*PhGlobals)->aPTE
|
|
#define Win (*PhGlobals)->win
|
|
#define QRect (*PhGlobals)->qRect
|
|
#define ARect (*PhGlobals)->aRect
|
|
#define Fallback (*PhGlobals)->fallback
|
|
#define OkButton (*PhGlobals)->controls[phcOkButton]
|
|
#define ListButton (*PhGlobals)->controls[phcListButton]
|
|
#define ToButton (*PhGlobals)->controls[phcToButton]
|
|
#define CcButton (*PhGlobals)->controls[phcCcButton]
|
|
#define BccButton (*PhGlobals)->controls[phcBccButton]
|
|
#define FingerButton (*PhGlobals)->controls[phcFingerButton]
|
|
#define Win (*PhGlobals)->win
|
|
#define Live (*PhGlobals)->live
|
|
#define Label (*PhGlobals)->label
|
|
#define XlOutControl (*PhGlobals)->controls[phcOutControl]
|
|
#define XlInControl (*PhGlobals)->controls[phcInControl]
|
|
#define Controls (*PhGlobals)->controls
|
|
#define SiteInfo (*PhGlobals)->siteinfo
|
|
#define UserList (*PhGlobals)->userList
|
|
#define Outlined (*PhGlobals)->outlined
|
|
#define FingerServer (*PhGlobals)->fingerServer
|
|
#define DirSvcType (*PhGlobals)->dirSvcType
|
|
#define DirSvcServer (*PhGlobals)->dirSvcServer
|
|
#define DirSvcPort (*PhGlobals)->dirSvcPort
|
|
#define DirSvcHostResolved (*PhGlobals)->dirSvcHostResolved
|
|
#define LDAPBaseObject (*PhGlobals)->ldapBaseObject
|
|
#define LDAPSearchScope (*PhGlobals)->ldapSearchScope
|
|
#define LDAPAttrList (*PhGlobals)->ldapAttrList
|
|
#define SelfURL (*PhGlobals)->selfURL
|
|
#define LastDirty (*PhGlobals)->lastDirty
|
|
#define QueryTicks (*PhGlobals)->queryTicks
|
|
#define DirtyTicks (*PhGlobals)->dirtyTicks
|
|
#define PhStream (*PhGlobals)->phStream
|
|
|
|
#define LockPhGlobals() LDRef(PhGlobals)
|
|
#define UnlockPhGlobals() UL(PhGlobals)
|
|
|
|
/************************************************************************
|
|
* private functions
|
|
************************************************************************/
|
|
DirSvcLookupType ProtocolToDirSvcType(ProtocolEnum protocolType);
|
|
void GetDirSvcHostPrefix(Str255 hostStr, Str255 prefixStr);
|
|
long GetDefaultDirSvcPort(DirSvcLookupType lookupType);
|
|
OSErr VerifyDirSvcHost(PStr host, long port);
|
|
OSErr FigureDirSvcType(PStr host, DirSvcLookupType *lookupType, PStr lookupHost, long *lookupPort, PStr urlQueryStr);
|
|
void SetDirSvcServerGlobals(DirSvcLookupType serverType, Str255 host, long port, PStr urlQueryStr);
|
|
Boolean GetDirSvcServerGlobals(DirSvcLookupType *serverType, Str255 host, long *port);
|
|
Boolean GetPhServerGlobals(Str255 host, long *port);
|
|
Boolean GetLDAPServerGlobals(Str255 host, long *port, short *searchScope, Str255 searchBaseObject, LDAPAttrListHdl *attributesList);
|
|
void SwitchDirSvcType(DirSvcLookupType lookupType);
|
|
DirSvcLookupType GetTargetDirSvcType(void);
|
|
void ResetServerGlobals(void);
|
|
short CurDirSvcButton(void);
|
|
void InvalLookupButtons(void);
|
|
void PhIdle(MyWindowPtr win);
|
|
OSErr PhAddNickContents(DragReference drag);
|
|
OSErr PhAddAddrContents(DragReference drag);
|
|
OSErr PhRememberField(UHandle **fields,short i,PStr data);
|
|
void PhClick(MyWindowPtr win, EventRecord *event);
|
|
Boolean PhKey(MyWindowPtr win, EventRecord *event);
|
|
Boolean PhMenu(MyWindowPtr win, int menu, int item, short modifiers);
|
|
void InvalPhWindowTop(void);
|
|
void PhUpdate(MyWindowPtr win);
|
|
void PhDidResize(MyWindowPtr win, Rect *oldContR);
|
|
void FormatLDAPEmailAddr(Str255 userName, Str255 emailAddr, Str255 combinedStr);
|
|
void LDAPEntryFilter(LDAPSessionHdl ldapSession, Str255 userNameStr, Str255 emailAddressStr, long startOffset, long endOffset);
|
|
OSErr OutputStrToAnswerField(Str255 theString);
|
|
OSErr OutputStrIndexToAnswerField(short strIndex);
|
|
OSErr OutputLDAPErrorMessage(Str255 errorStr, OSErr errCode, Boolean translateLDAPErrCodes);
|
|
OSErr ReportLDAPSearchResults(LDAPSessionHdl ldapSession);
|
|
OSErr DoLDAPLookup(Str255 ldapServer, int ldapPortNo, Str255 queryStr, Boolean queryStrIsURLQuery);
|
|
void PerformQuery(DirSvcLookupType lookupType,PStr withCommand, Boolean cmdIsURLQuery,Boolean emptyFirst);
|
|
void PhButton(MyWindowPtr win,ControlHandle button,long modifiers,short part);
|
|
Boolean PhClose(MyWindowPtr win);
|
|
int QiLine(TransStream stream,short *ordinal, UPtr text, long *size);
|
|
short ContactQi(TransStream stream);
|
|
short SendQiCommand(TransStream stream,UPtr cmd);
|
|
short GetQiResponse(TransStream stream,PStr cmd);
|
|
void CloseQi(TransStream stream);
|
|
void PhFocus(PETEHandle pte);
|
|
void DoFinger(TransStream stream,UPtr cmd);
|
|
Boolean PhPosition(Boolean save, MyWindowPtr win);
|
|
Boolean PhApp1(MyWindowPtr win, EventRecord *event);
|
|
PhWinItemIndex CalcPhHelpItem(MyWindowPtr win, Point mouseLoc, Rect *itemRect);
|
|
void PhHelp(MyWindowPtr win,Point mouse);
|
|
void IncrementPhServer(UPtr serverName);
|
|
void MakeFallbackName(UPtr serverName, short fallback);
|
|
void NotePhServer(UPtr serverName);
|
|
void PhActivate(MyWindowPtr win);
|
|
void SetPhTablePref(ControlHandle c,short pref);
|
|
PStr GetFingerServerName(PStr serverName);
|
|
PStr GetDirSvcServerName(PStr serverName);
|
|
OSErr UpdateSiteInfo(TransStream stream);
|
|
void ZapUserList(void);
|
|
void FormatPhEmail(PStr rem1, PStr rem2, PStr name, UserEntryHandle ueh);
|
|
void PhOutline(short newControl);
|
|
void PhSetGreys(void);
|
|
Boolean CanQuery(void);
|
|
Boolean CanAddress(void);
|
|
OSErr InsertPhAddress(short txeIndex,short modifiers);
|
|
void RedisplayPhHost(void);
|
|
void TempPhHost(PStr host, DirSvcLookupType lookupType, PStr query);
|
|
Boolean UEHIsSelected(UserEntryHandle ueh);
|
|
OSErr PhMakeNick(void);
|
|
Boolean UEHIsSelected(UserEntryHandle ueh);
|
|
Boolean CurQueryTextIsURL(void);
|
|
Boolean PhURLQuery(void);
|
|
void PhListServers(void);
|
|
void PhListResponse(TransStream stream,Boolean emptyFirst);
|
|
void ZapFields(UHandle **fields);
|
|
PStr PhMakeURL(PStr url);
|
|
PStr LDAPMakeURL(PStr url);
|
|
static Boolean PhFind(MyWindowPtr win,PStr what);
|
|
pascal OSErr PhSetDragContents(PETEHandle pte,DragReference drag);
|
|
OSErr PhListConnectError(short error);
|
|
|
|
DirSvcLookupType ProtocolToDirSvcType(ProtocolEnum protocolType)
|
|
|
|
{
|
|
switch (protocolType)
|
|
{
|
|
case proPh:
|
|
case proPh2:
|
|
return phLookup;
|
|
case proFinger:
|
|
return fingerLookup;
|
|
case proLDAP:
|
|
return ldapLookup;
|
|
}
|
|
return invalidLookupType;
|
|
}
|
|
|
|
|
|
void GetDirSvcHostPrefix(Str255 hostStr, Str255 prefixStr)
|
|
|
|
{
|
|
UPtr curSpot;
|
|
|
|
|
|
*prefixStr = 0;
|
|
curSpot = hostStr + 1;
|
|
PToken(hostStr, prefixStr, &curSpot, ".");
|
|
}
|
|
|
|
|
|
long GetDefaultDirSvcPort(DirSvcLookupType lookupType)
|
|
|
|
{
|
|
short port;
|
|
|
|
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
return GetRLong(PH_PORT);
|
|
|
|
case ldapLookup:
|
|
port = GetRLong(LDAP_PORT_REALLY);
|
|
if (!port)
|
|
port = LDAP_PORT;
|
|
return port;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
OSErr VerifyDirSvcHost(PStr host, long port)
|
|
|
|
{
|
|
OSErr err;
|
|
TransStream tempStream;
|
|
|
|
|
|
if (!host || !*host)
|
|
return paramErr;
|
|
|
|
tempStream = nil;
|
|
err = NewTransStream(&tempStream);
|
|
if (err)
|
|
return err;
|
|
|
|
err = ConnectTrans(tempStream, host, port, true,GetRLong(SHORT_OPEN_TIMEOUT));
|
|
DestroyTrans(tempStream); /* ignore error */
|
|
ZapTransStream(&tempStream);
|
|
return err;
|
|
}
|
|
|
|
|
|
OSErr FigureDirSvcType(PStr host, DirSvcLookupType *lookupType, PStr lookupHost, long *lookupPort, PStr urlQueryStr)
|
|
|
|
{
|
|
OSErr err;
|
|
ProtocolEnum protocolType;
|
|
Str255 urlProtocolStr, urlHostStr;
|
|
long urlPort;
|
|
TransStream tempStream;
|
|
DirSvcLookupType curTestType;
|
|
long curTestPort;
|
|
DirSvcLookupType guessType;
|
|
Str255 guessPrefix;
|
|
Str255 testPrefix;
|
|
|
|
|
|
*lookupType = invalidLookupType;
|
|
*lookupPort = 0;
|
|
if (host != lookupHost)
|
|
*lookupHost = 0;
|
|
*urlQueryStr = 0;
|
|
|
|
if (!host || !*host)
|
|
return paramErr;
|
|
|
|
err = ParseURL(host, urlProtocolStr, urlHostStr, urlQueryStr);
|
|
if (!err)
|
|
{
|
|
protocolType = FindSTRNIndex(ProtocolStrn, urlProtocolStr);
|
|
curTestType = ProtocolToDirSvcType(protocolType);
|
|
switch (curTestType)
|
|
{
|
|
case phLookup:
|
|
case ldapLookup:
|
|
FixURLString(urlQueryStr);
|
|
FixURLString(urlHostStr);
|
|
if (!ParsePortFromHost(urlHostStr, urlHostStr, &urlPort))
|
|
urlPort = GetDefaultDirSvcPort(curTestType);
|
|
*lookupType = curTestType;
|
|
BlockMoveData(urlHostStr, lookupHost, *urlHostStr + 1);
|
|
*lookupPort = urlPort;
|
|
return noErr;
|
|
default:
|
|
return paramErr; /* host is a URL, but not for Ph or LDAP */
|
|
}
|
|
}
|
|
|
|
tempStream = nil;
|
|
err = NewTransStream(&tempStream);
|
|
if (err)
|
|
return err;
|
|
|
|
guessType = phLookup;
|
|
GetDirSvcHostPrefix(host, testPrefix);
|
|
if (*testPrefix)
|
|
{
|
|
GetRString(guessPrefix, LDAP_HOST_COMMON_PREFIX);
|
|
if (EqualString(guessPrefix, testPrefix, false, true))
|
|
guessType = ldapLookup;
|
|
}
|
|
|
|
if (guessType == phLookup)
|
|
{
|
|
curTestType = phLookup;
|
|
curTestPort = GetDefaultDirSvcPort(phLookup);
|
|
err = ConnectTrans(tempStream, host, curTestPort, true,GetRLong(SHORT_OPEN_TIMEOUT));
|
|
if (!err)
|
|
goto FoundExit;
|
|
|
|
DestroyTrans(tempStream); /* ignore error */
|
|
|
|
curTestType = ldapLookup;
|
|
curTestPort = GetDefaultDirSvcPort(ldapLookup);
|
|
err = ConnectTrans(tempStream, host, curTestPort, true,GetRLong(SHORT_OPEN_TIMEOUT));
|
|
if (!err)
|
|
goto FoundExit;
|
|
}
|
|
else
|
|
{
|
|
curTestType = ldapLookup;
|
|
curTestPort = GetDefaultDirSvcPort(ldapLookup);
|
|
err = ConnectTrans(tempStream, host, curTestPort, true,GetRLong(SHORT_OPEN_TIMEOUT));
|
|
if (!err)
|
|
goto FoundExit;
|
|
|
|
DestroyTrans(tempStream); /* ignore error */
|
|
|
|
curTestType = phLookup;
|
|
curTestPort = GetDefaultDirSvcPort(phLookup);
|
|
err = ConnectTrans(tempStream, host, curTestPort, true,GetRLong(SHORT_OPEN_TIMEOUT));
|
|
if (!err)
|
|
goto FoundExit;
|
|
}
|
|
|
|
ZapTransStream(&tempStream);
|
|
return err; /* FINISH *//* should we just return noErr? */
|
|
|
|
|
|
FoundExit:
|
|
DestroyTrans(tempStream);
|
|
ZapTransStream(&tempStream);
|
|
*lookupType = curTestType;
|
|
if (host != lookupHost)
|
|
BlockMoveData(host, lookupHost, *host + 1);
|
|
*lookupPort = curTestPort;
|
|
return noErr;
|
|
}
|
|
|
|
|
|
void SetDirSvcServerGlobals(DirSvcLookupType serverType, Str255 host, long port, PStr urlQueryStr)
|
|
|
|
{
|
|
DirSvcType = serverType;
|
|
BlockMoveData(host, DirSvcServer, *host + 1);
|
|
DirSvcPort = port;
|
|
DirSvcHostResolved = true;
|
|
#ifdef LDAP_ENABLED
|
|
LDAPBaseObject[0] = 0;
|
|
LDAPSearchScope = LDAP_SCOPE_SUBTREE;
|
|
if (LDAPAttrList)
|
|
{
|
|
DisposeLDAPAttrList(LDAPAttrList);
|
|
LDAPAttrList = nil;
|
|
}
|
|
if (serverType == ldapLookup)
|
|
{
|
|
LockPhGlobals();
|
|
ParseLDAPURLQuery(urlQueryStr, LDAPBaseObject, &LDAPAttrList, &LDAPSearchScope, nil); /* ignore errors */
|
|
UnlockPhGlobals();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
Boolean GetDirSvcServerGlobals(DirSvcLookupType *serverType, Str255 host, long *port)
|
|
|
|
{
|
|
OSErr err;
|
|
DirSvcLookupType hostType;
|
|
Str255 actualHost;
|
|
long serverPort;
|
|
Str255 urlQueryStr;
|
|
|
|
|
|
if (!DirSvcHostResolved)
|
|
{
|
|
LockPhGlobals();
|
|
err = FigureDirSvcType(DirSvcServer, &hostType, actualHost, &serverPort, urlQueryStr);
|
|
UnlockPhGlobals();
|
|
if (err)
|
|
return false;
|
|
DirSvcType = hostType;
|
|
BlockMoveData(actualHost, DirSvcServer, *actualHost + 1);
|
|
DirSvcPort = serverPort;
|
|
#ifdef LDAP_ENABLED
|
|
LDAPBaseObject[0] = 0;
|
|
LDAPSearchScope = LDAP_SCOPE_SUBTREE;
|
|
if (LDAPAttrList)
|
|
{
|
|
DisposeLDAPAttrList(LDAPAttrList);
|
|
LDAPAttrList = nil;
|
|
}
|
|
if (hostType == ldapLookup)
|
|
{
|
|
LockPhGlobals();
|
|
ParseLDAPURLQuery(urlQueryStr, LDAPBaseObject, &LDAPAttrList, &LDAPSearchScope, nil); /* ignore errors */
|
|
UnlockPhGlobals();
|
|
}
|
|
#endif
|
|
DirSvcHostResolved = true;
|
|
RedisplayPhHost();
|
|
}
|
|
if (serverType)
|
|
*serverType = DirSvcType;
|
|
if (host)
|
|
BlockMoveData(DirSvcServer, host, *DirSvcServer + 1);
|
|
if (port)
|
|
*port = DirSvcPort;
|
|
return true;
|
|
}
|
|
|
|
|
|
Boolean GetPhServerGlobals(Str255 host, long *port)
|
|
|
|
{
|
|
DirSvcLookupType serverType;
|
|
Str255 host_;
|
|
long port_;
|
|
|
|
|
|
if (!GetDirSvcServerGlobals(&serverType, host_, &port_))
|
|
return false;
|
|
if (serverType != phLookup)
|
|
return false;
|
|
if (host)
|
|
BlockMoveData(host_, host, *host_ + 1);
|
|
if (port)
|
|
*port = port_;
|
|
return true;
|
|
}
|
|
|
|
|
|
Boolean GetLDAPServerGlobals(Str255 host, long *port, short *searchScope, Str255 searchBaseObject, LDAPAttrListHdl *attributesList)
|
|
|
|
{
|
|
DirSvcLookupType serverType;
|
|
Str255 host_;
|
|
long port_;
|
|
|
|
|
|
if (!GetDirSvcServerGlobals(&serverType, host_, &port_))
|
|
return false;
|
|
if (serverType != ldapLookup)
|
|
return false;
|
|
if (host)
|
|
BlockMoveData(host_, host, *host_ + 1);
|
|
if (port)
|
|
*port = port_;
|
|
if (searchScope)
|
|
*searchScope = LDAPSearchScope;
|
|
if (searchBaseObject)
|
|
BlockMoveData(LDAPBaseObject, searchBaseObject, *LDAPBaseObject + 1);
|
|
if (attributesList)
|
|
*attributesList = LDAPAttrList;
|
|
return true;
|
|
}
|
|
|
|
|
|
DirSvcLookupType GetCurDirSvcType(void)
|
|
|
|
{
|
|
DirSvcLookupType lookupType;
|
|
|
|
|
|
lookupType = GetPrefLong(PREF_CUR_DIR_SVC_TYPE);
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
case ldapLookup:
|
|
case genericLookup:
|
|
return genericLookup;
|
|
case fingerLookup:
|
|
return UseCTB ? genericLookup : fingerLookup;
|
|
default:
|
|
return genericLookup;
|
|
}
|
|
}
|
|
|
|
|
|
void SetCurDirSvcType(DirSvcLookupType lookupType)
|
|
|
|
{
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
case ldapLookup:
|
|
case genericLookup:
|
|
lookupType = genericLookup;
|
|
break;
|
|
case fingerLookup:
|
|
if (UseCTB)
|
|
lookupType = genericLookup;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
SetPrefLong(PREF_CUR_DIR_SVC_TYPE, lookupType);
|
|
}
|
|
|
|
|
|
void SwitchDirSvcType(DirSvcLookupType lookupType)
|
|
|
|
{
|
|
if (lookupType != GetCurDirSvcType())
|
|
{
|
|
SetCurDirSvcType(lookupType);
|
|
InvalLookupButtons();
|
|
RedisplayPhHost();
|
|
}
|
|
}
|
|
|
|
|
|
DirSvcLookupType GetTargetDirSvcType(void)
|
|
|
|
{
|
|
DirSvcLookupType lookupType;
|
|
|
|
|
|
lookupType = GetCurDirSvcType();
|
|
if (lookupType == genericLookup)
|
|
return DirSvcType;
|
|
else
|
|
return lookupType;
|
|
}
|
|
|
|
|
|
void ResetServerGlobals(void)
|
|
|
|
{
|
|
Str255 hostStr;
|
|
|
|
|
|
GetFingerServerName(hostStr);
|
|
PSCopy(FingerServer, hostStr);
|
|
|
|
LockPhGlobals();
|
|
GetDirSvcServerName(DirSvcServer);
|
|
UnlockPhGlobals();
|
|
DirSvcPort = 0;
|
|
DirSvcType = genericLookup;
|
|
DirSvcHostResolved = false;
|
|
#ifdef LDAP_ENABLED
|
|
LDAPBaseObject[0] = 0;
|
|
LDAPSearchScope = LDAP_SCOPE_SUBTREE;
|
|
if (LDAPAttrList)
|
|
{
|
|
DisposeLDAPAttrList(LDAPAttrList);
|
|
LDAPAttrList = nil;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
short CurDirSvcButton(void)
|
|
|
|
{
|
|
DirSvcLookupType lookupType;
|
|
|
|
|
|
lookupType = GetCurDirSvcType();
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
case ldapLookup:
|
|
case genericLookup:
|
|
return phcOkButton;
|
|
case fingerLookup:
|
|
return phcFingerButton;
|
|
}
|
|
return phcOkButton;
|
|
}
|
|
|
|
|
|
void InvalLookupButtons(void)
|
|
|
|
{
|
|
Rect r,rFinger;
|
|
|
|
GetControlBounds(OkButton,&r);
|
|
GetControlBounds(FingerButton,&rFinger);
|
|
r.left = rFinger.left;
|
|
InsetRect(&r, -4, -4);
|
|
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* OpenPh - open the ph window
|
|
************************************************************************/
|
|
OSErr OpenPh(PStr initialQuery)
|
|
{
|
|
WindowPtr winWP;
|
|
Rect r;
|
|
short item;
|
|
short cntl;
|
|
Str255 scratch;
|
|
OSErr err;
|
|
|
|
CycleBalls();
|
|
if (!SelectOpenWazoo(PH_WIN) && !PhGlobals)
|
|
{
|
|
if (!(PhGlobals=NewZH(PhType)))
|
|
{WarnUser(MEM_ERR,MemError()); goto fail;}
|
|
Outlined = -1;
|
|
|
|
ResetServerGlobals();
|
|
|
|
LDRef(PhGlobals);
|
|
|
|
if (!(Win = GetNewMyWindow(PH_WIND,nil,nil,BehindModal,False,False,PH_WIN)))
|
|
{WarnUser(MEM_ERR,MemError()); goto fail;}
|
|
winWP = GetMyWindowWindowPtr (Win);
|
|
SetPort_(GetWindowPort(winWP));
|
|
//ConfigFontSetup(Win);
|
|
MySetThemeWindowBackground(Win,kThemeListViewBackgroundBrush,False);
|
|
|
|
for (cntl=phcOkButton;cntl<(NewTables?phcLimit:phcInControl);cntl++)
|
|
{
|
|
if (!(Controls[cntl]=GetNewControl(PhCntlIds[cntl],winWP)))
|
|
{WarnUser(MEM_ERR,MemError()); goto fail;}
|
|
if (cntl!=phcOkButton && cntl!=phcFingerButton) LetsGetSmall(Controls[cntl]);
|
|
}
|
|
SetControlTitle(ToButton,GetRString(scratch,HEADER_LABEL_STRN+TO_HEAD));
|
|
SetControlTitle(CcButton,GetRString(scratch,HEADER_LABEL_STRN+CC_HEAD));
|
|
SetControlTitle(BccButton,GetRString(scratch,HEADER_LABEL_STRN+BCC_HEAD));
|
|
ButtonFit(ToButton);
|
|
ButtonFit(CcButton);
|
|
ButtonFit(BccButton);
|
|
|
|
#ifdef TWO
|
|
if (NewTables)
|
|
{
|
|
item = AddXlateTables(False,GetPrefLong(PREF_PH_IN),True,Control2Menu(XlInControl));
|
|
SetControlMaximum(XlInControl,CountMenuItems(Control2Menu(XlInControl)));
|
|
SetControlValue(XlInControl,MAX(1,item));
|
|
item = AddXlateTables(True,GetPrefLong(PREF_PH_OUT),True,Control2Menu(XlOutControl));
|
|
SetControlMaximum(XlOutControl,CountMenuItems(Control2Menu(XlOutControl)));
|
|
SetControlValue(XlOutControl,MAX(1,item));
|
|
}
|
|
#endif
|
|
|
|
#ifdef NEVER
|
|
if (RunType==Debugging)
|
|
{
|
|
Rect r;
|
|
short type;
|
|
Handle h;
|
|
|
|
GetControlBounds(ToButton,&r);
|
|
NewControl((WindowPtr)Dlog, &r, "", true, 0,0,0, DEBUG_CDEF<<4, 0);
|
|
}
|
|
#endif
|
|
|
|
r = Win->contR;
|
|
|
|
if (!(err=PeteCreate(Win,&QPTE,peClearAllReturns,nil)))
|
|
err=PeteCreate(Win,&APTE,peVScroll,nil);
|
|
if (err) {WarnUser(PETE_ERR,err); goto fail;}
|
|
|
|
PeteFontAndSize(APTE,FixedID,FixedSize);
|
|
|
|
// (jp) We'll support a few nickname scanning features for the query field
|
|
// Counter-productive at the moment. SD 5/12/99 // SetNickScanning (QPTE, nickHighlight | nickComplete, kNickScanAllAliasFiles, nil, nil, nil);
|
|
// (jp) putting back only nick completion (but not expansion)
|
|
SetNickScanning (QPTE, nickComplete, kNickScanAllAliasFiles, PhNickFieldCheck, nil, nil);
|
|
|
|
err = NewTransStream(&PhStream);
|
|
if (err) {WarnUser(MEM_ERR,err); goto fail;}
|
|
|
|
(*PeteExtra(APTE))->frame = True;
|
|
(*PeteExtra(QPTE))->frame = True;
|
|
PETESetCallback(PETE,APTE,(void*)PhSetDragContents,peSetDragContents);
|
|
UL(PhGlobals);
|
|
NewPhHost();
|
|
Win->close = PhClose;
|
|
Win->activate = PhActivate;
|
|
Win->click = PhClick;
|
|
Win->menu = PhMenu;
|
|
Win->key = PhKey;
|
|
Win->button = PhButton;
|
|
Win->idle = PhIdle;
|
|
PhFocus(QPTE);
|
|
Win->position = PhPosition;
|
|
Win->dontControl = True;
|
|
Win->vPitch = FontLead;
|
|
Win->update = PhUpdate;
|
|
Win->app1 = PhApp1;
|
|
Win->help = PhHelp;
|
|
Win->find = PhFind;
|
|
SetWinMinSize(Win,320,12*FontLead);
|
|
Win->didResize = PhDidResize;
|
|
MyWindowDidResize(Win,&r);
|
|
ShowControl(OkButton);
|
|
ShowControl(FingerButton);
|
|
ShowMyWindow(winWP);
|
|
}
|
|
UserSelectWindow(GetMyWindowWindowPtr(Win));
|
|
|
|
if (initialQuery)
|
|
{
|
|
PeteSetTextPtr(QPTE,initialQuery+1,*initialQuery);
|
|
PerformQuery(genericLookup,nil,false,true);
|
|
}
|
|
|
|
PhSetGreys();
|
|
|
|
return(noErr);
|
|
|
|
fail:
|
|
PhClose(Win);
|
|
return(1);
|
|
}
|
|
|
|
Boolean PhNickFieldCheck (PETEHandle pte)
|
|
|
|
{
|
|
return (false);
|
|
}
|
|
|
|
#pragma segment Menu
|
|
/**********************************************************************
|
|
* PhCanMakeNick - can we make a nickname?
|
|
**********************************************************************/
|
|
Boolean PhCanMakeNick(void)
|
|
{
|
|
return (PhGlobals && GetMyWindowWindowPtr(Win)==FrontWindow_() && CanAddress());
|
|
}
|
|
|
|
#pragma segment Ph
|
|
/**********************************************************************
|
|
*
|
|
**********************************************************************/
|
|
void PhIdle(MyWindowPtr win)
|
|
{
|
|
if (!InBG && GetMyWindowWindowPtr(win)==FrontWindow_())
|
|
{
|
|
long dirty = PeteIsDirty(QPTE);
|
|
Str255 query;
|
|
Str31 retWord;
|
|
long ticks = TickCount();
|
|
Boolean live;
|
|
DirSvcLookupType lookupType;
|
|
|
|
lookupType = GetTargetDirSvcType();
|
|
live = PrefIsSet(PREF_PH_LIVE) && (lookupType != fingerLookup);
|
|
|
|
PhSetGreys();
|
|
|
|
if (dirty!=LastDirty)
|
|
{
|
|
LastDirty = dirty;
|
|
DirtyTicks = ticks;
|
|
}
|
|
|
|
if (live && DirtyTicks>QueryTicks && *PeteString(query,QPTE)>=GetRLong(PH_LIVE_MIN_CHARS))
|
|
{
|
|
if (ticks-DirtyTicks>GetRLong(PH_LIVE_MIN_TICKS))
|
|
{
|
|
if (!CurQueryTextIsURL())
|
|
{
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
if (!PFindSub(GetRString(retWord,PH_RETURN_KEYWORD),query))
|
|
{
|
|
PCatC(query,'*');
|
|
PerformQuery(phLookup,query,false,true);
|
|
QueryTicks = TickCount();
|
|
}
|
|
break;
|
|
|
|
case ldapLookup:
|
|
if (query[1]!='(')
|
|
{
|
|
PCatC(query,'*');
|
|
PerformQuery(lookupType,query,false,true);
|
|
QueryTicks = TickCount();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
PerformQuery(lookupType,query,false,true);
|
|
QueryTicks = TickCount();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QueryTicks = TickCount();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Live)
|
|
{
|
|
if ((ticks-QueryTicks)>GetRLong(InBG ? PH_BG_IDLE : PH_FG_IDLE)*60)
|
|
if (lookupType == phLookup)
|
|
PhKill();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* PhURLLookup - lookup a URL from the ph window
|
|
**********************************************************************/
|
|
OSErr PhURLLookup(ProtocolEnum protocol,PStr host,PStr query,Handle *result)
|
|
{
|
|
DirSvcLookupType lookupType;
|
|
|
|
|
|
lookupType = ProtocolToDirSvcType(protocol);
|
|
if (lookupType == invalidLookupType)
|
|
return paramErr;
|
|
|
|
SetPort_(GetMyWindowCGrafPtr(Win));
|
|
|
|
/*
|
|
* re-aim server if need be
|
|
*/
|
|
if (*host)
|
|
TempPhHost(host, lookupType, query);
|
|
|
|
/*
|
|
* enter query
|
|
*/
|
|
if (!SelfURL || *query) PeteSetTextPtr(QPTE,query+1,*query);
|
|
else PeteSelect(Win,QPTE,0,0x7fffffff);
|
|
|
|
/*
|
|
* do it
|
|
*/
|
|
if (*query)
|
|
PerformQuery(lookupType, query, true,true);
|
|
else
|
|
{
|
|
SwitchDirSvcType(lookupType);
|
|
PhFocus(QPTE);
|
|
}
|
|
|
|
/*
|
|
* result?
|
|
*/
|
|
if (result) PeteGetRawText(APTE,result);
|
|
|
|
return(noErr);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* TempPhHost - enter a ph host, but don't make it the default
|
|
**********************************************************************/
|
|
void TempPhHost(PStr host, DirSvcLookupType lookupType, PStr query)
|
|
{
|
|
Str255 server;
|
|
long port;
|
|
|
|
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
if (!ParsePortFromHost(host,server,&port))
|
|
port = GetDefaultDirSvcPort(phLookup);
|
|
SetDirSvcServerGlobals(phLookup, server, port, query);
|
|
break;
|
|
|
|
case fingerLookup:
|
|
PCopy(FingerServer,host);
|
|
break;
|
|
|
|
#ifdef LDAP_ENABLED
|
|
case ldapLookup:
|
|
if (!ParsePortFromHost(host,server,&port))
|
|
port = GetDefaultDirSvcPort(ldapLookup);
|
|
SetDirSvcServerGlobals(ldapLookup, server, port, query);
|
|
// Now fix the query
|
|
if (!ParseLDAPURLQuery(query,nil,nil,nil,server))
|
|
PCopy(query,server); // the real query goes there
|
|
break;
|
|
#endif
|
|
default:
|
|
return;
|
|
}
|
|
|
|
RedisplayPhHost();
|
|
PeteSetTextPtr(APTE,nil,0);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhSetDragContents - add the right stuff to a drag
|
|
**********************************************************************/
|
|
pascal OSErr PhSetDragContents(PETEHandle pte,DragReference drag)
|
|
{
|
|
OSErr err;
|
|
|
|
if (!(err = PhAddNickContents(drag)))
|
|
err = PhAddAddrContents(drag);
|
|
return(err ? err : handlerNotFoundErr);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhAddNickContents - add a NICK_FLAVOR to the drag
|
|
**********************************************************************/
|
|
OSErr PhAddNickContents(DragReference drag)
|
|
{
|
|
OSErr err = noErr;
|
|
Accumulator nickData;
|
|
UserEntryHandle ueh;
|
|
Accumulator noteData;
|
|
Str255 scratch, label;
|
|
long len;
|
|
short nf;
|
|
short dummy=-1;
|
|
NicknameTagMapRec tagMap;
|
|
Boolean haveTagMap;
|
|
Str255 serviceName;
|
|
|
|
Zero(nickData);
|
|
Zero(noteData);
|
|
|
|
haveTagMap = GetNicknameTagMap (GetRString (serviceName, ProtocolStrn + proPh), DirSvcServer, &tagMap) ? false : true;
|
|
|
|
/*
|
|
* gather the data
|
|
*/
|
|
if (!(err=AccuInit(&nickData)))
|
|
for (ueh=UserList;!err && ueh;ueh = (*ueh)->next)
|
|
if (UEHIsSelected(ueh) && (*ueh)->fields && !(err=AccuInit(¬eData)))
|
|
{
|
|
// Space holders for the address book and nickname indices (which will be ignored)
|
|
err=AccuAddPtr(&nickData,(void*)&dummy,sizeof(dummy));
|
|
if (!err)
|
|
err=AccuAddPtr(&nickData,(void*)&dummy,sizeof(dummy));
|
|
// next, the nickname
|
|
if ((*(*ueh)->fields)[0])
|
|
{
|
|
len = GetHandleSize((*(*ueh)->fields)[0]);
|
|
MakePStr(scratch,*(*(*ueh)->fields)[0],len);
|
|
}
|
|
else PSCopy(scratch,(*ueh)->name);
|
|
SanitizeFN(label,scratch,NICK_BAD_CHAR,NICK_REP_CHAR,false);
|
|
if (err = AccuAddPtr(&nickData,label,*label+1)) break;
|
|
|
|
// length and address
|
|
PSCopy(scratch,(*ueh)->address);
|
|
ShortAddr(label,scratch);
|
|
len = *label;
|
|
if (err=AccuAddPtr(&nickData,(void*)&len,sizeof(len))) break;
|
|
if (err = AccuAddStr(&nickData,label)) break;
|
|
|
|
// note data
|
|
for (nf=HandleCount((*ueh)->fields)-1;nf;nf--)
|
|
if ((*(*ueh)->fields)[nf])
|
|
{
|
|
// open bracket
|
|
if (err=AccuAddChar(¬eData,'<')) break;
|
|
|
|
// field name and colon
|
|
if (haveTagMap)
|
|
GetIndNicknameTag (&tagMap, nf, label);
|
|
else
|
|
GetRString(label,PhNickNickStrn+nf+1);
|
|
if (err=AccuAddStr(¬eData,label)) break;
|
|
if (err=AccuAddChar(¬eData,':')) break;
|
|
|
|
//data
|
|
#ifdef KNOWN_PROBLEM
|
|
resolve problem involving quoting < and > in data
|
|
#endif
|
|
if (err=AccuAddHandle(¬eData,(*(*ueh)->fields)[nf])) break;
|
|
|
|
//closing >
|
|
if (err=AccuAddChar(¬eData,'>')) break;
|
|
}
|
|
if (err) break;
|
|
|
|
// the name
|
|
if (err=AccuAddChar(¬eData,'<')) break;
|
|
GetRString(label,NickManKeyStrn+1);
|
|
if (err=AccuAddStr(¬eData,label)) break;
|
|
if (err=AccuAddChar(¬eData,':')) break;
|
|
PSCopy(label,(*ueh)->name);
|
|
if (err=AccuAddStr(¬eData,label)) break;
|
|
if (err=AccuAddChar(¬eData,'>')) break;
|
|
|
|
// now add it
|
|
AccuTrim(¬eData);
|
|
len = noteData.offset;
|
|
if (err=AccuAddPtr(&nickData,(void*)&len,sizeof(len))) break;
|
|
if (err=AccuAddHandle(&nickData,noteData.data)) break;
|
|
ZapHandle(noteData.data);
|
|
Zero(noteData);
|
|
}
|
|
|
|
/*
|
|
* add them to the drag
|
|
*/
|
|
if (!err && nickData.offset)
|
|
{
|
|
// add to the drag
|
|
err = AddDragItemFlavor(drag,1,kNickDragType,LDRef(nickData.data),nickData.offset,0);
|
|
}
|
|
|
|
ZapHandle(nickData.data);
|
|
ZapHandle(noteData.data);
|
|
DisposeNicknameTagMap (&tagMap);
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhAddAddrContents - add an A822_FLAVOR to the drag
|
|
**********************************************************************/
|
|
OSErr PhAddAddrContents(DragReference drag)
|
|
{
|
|
OSErr err = noErr;
|
|
Accumulator addresses;
|
|
UserEntryHandle ueh;
|
|
Str15 commaSpace;
|
|
|
|
Zero(addresses);
|
|
GetRString(commaSpace,COMMA_SPACE);
|
|
|
|
/*
|
|
* gather the addresses
|
|
*/
|
|
if (!(err=AccuInit(&addresses)))
|
|
for (ueh=UserList;!err && ueh;ueh = (*ueh)->next)
|
|
if (UEHIsSelected(ueh))
|
|
{
|
|
LDRef(ueh);
|
|
err = AccuAddStr(&addresses,(*ueh)->address);
|
|
UL(ueh);
|
|
if (!err) err = AccuAddStr(&addresses,commaSpace);
|
|
}
|
|
|
|
/*
|
|
* add them to the drag
|
|
*/
|
|
if (!err && addresses.offset>*commaSpace)
|
|
{
|
|
// trim unneeded trailing comma
|
|
addresses.offset -= *commaSpace;
|
|
AccuTrim(&addresses);
|
|
|
|
// add to the drag
|
|
err = AddDragItemFlavor(drag,1,A822_FLAVOR,LDRef(addresses.data),addresses.offset,0);
|
|
}
|
|
|
|
// and kill the temp data
|
|
ZapHandle(addresses.data);
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhActivate
|
|
************************************************************************/
|
|
void PhActivate(MyWindowPtr win)
|
|
{
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhFind - find in the window
|
|
**********************************************************************/
|
|
static Boolean PhFind(MyWindowPtr win,PStr what)
|
|
{
|
|
return FindInPTE(win,APTE,what);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhOutline - outline the proper button
|
|
**********************************************************************/
|
|
void PhOutline(short newControl)
|
|
{
|
|
if (newControl!=Outlined)
|
|
{
|
|
if (Outlined>=0) OutlineControl(Controls[Outlined],False);
|
|
Outlined = newControl;
|
|
if (Outlined>=0) OutlineControl(Controls[Outlined],True);
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhSetGreys - make sure the right greys (and outlines) are set
|
|
**********************************************************************/
|
|
void PhSetGreys(void)
|
|
{
|
|
Str255 contents;
|
|
Boolean hasQuery = CanQuery();
|
|
Boolean hasAnswer = *PeteSString(contents,APTE);
|
|
Boolean canAddress = hasAnswer && CanAddress();
|
|
short defaultBtn;
|
|
|
|
SetGreyControl(FingerButton,UseCTB || !hasQuery);
|
|
SetGreyControl(OkButton,!hasQuery);
|
|
|
|
SetGreyControl(ToButton,!canAddress);
|
|
SetGreyControl(CcButton,!canAddress);
|
|
SetGreyControl(BccButton,!canAddress);
|
|
|
|
if (Win->pte==QPTE)
|
|
{
|
|
if (hasQuery)
|
|
{
|
|
defaultBtn = CurDirSvcButton();
|
|
PhOutline(defaultBtn);
|
|
}
|
|
else
|
|
PhOutline(-1);
|
|
}
|
|
else
|
|
PhOutline(canAddress?phcToButton:-1);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CanQuery - has the user typed something into the query line?
|
|
**********************************************************************/
|
|
Boolean CanQuery(void)
|
|
{
|
|
Str255 contents;
|
|
|
|
|
|
return (*PeteSString(contents, QPTE)) ? true : false;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CanAddress - can we possibly address mail?
|
|
**********************************************************************/
|
|
Boolean CanAddress(void)
|
|
{
|
|
UserEntryHandle ueh;
|
|
Str255 contents;
|
|
|
|
if (!*PeteSString(contents,APTE)) return(False); /* we do have some results */
|
|
if (!UserList) return(False); /* those results do have addresses attached */
|
|
|
|
for (ueh=UserList;ueh;ueh = (*ueh)->next)
|
|
{
|
|
if (UEHIsSelected(ueh) && *(*ueh)->address) return(True);
|
|
}
|
|
|
|
/*
|
|
* selection is not in any user whose email address we know
|
|
*/
|
|
return(False);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* UEHIsSelected - is a ueh selected?
|
|
**********************************************************************/
|
|
Boolean UEHIsSelected(UserEntryHandle ueh)
|
|
{
|
|
long start,stop;
|
|
UHandle textH;
|
|
|
|
if (Win->pte==QPTE) return(True);
|
|
|
|
if (PeteGetTextAndSelection(APTE,&textH,&start,&stop)) return(False);
|
|
if (start>=(*ueh)->end) return(False);
|
|
if (stop<=(*ueh)->start) return(False);
|
|
|
|
return(True);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhPosition - ph window position
|
|
************************************************************************/
|
|
Boolean PhPosition(Boolean save, MyWindowPtr win)
|
|
{
|
|
Str31 ph;
|
|
|
|
MyGetItem(GetMHandle(WINDOW_MENU),WIN_PH_ITEM,ph);
|
|
SetWTitle_(GetMyWindowWindowPtr(Win),ph);
|
|
return(PositionPrefsTitle(save,win));
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhButton - handle a button click in the ph window
|
|
************************************************************************/
|
|
void PhButton(MyWindowPtr win,ControlHandle button,long modifiers,short part)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
short which;
|
|
|
|
#ifdef TWO
|
|
if (button && button==XlOutControl)
|
|
SetPhTablePref(button,PREF_PH_OUT);
|
|
else if (button && button==XlInControl)
|
|
SetPhTablePref(button,PREF_PH_IN);
|
|
else if (button==ListButton)
|
|
{
|
|
if (modifiers&optionKey)
|
|
NewPhHost();
|
|
else
|
|
PhListServers();
|
|
}
|
|
else
|
|
#endif
|
|
if (part==kControlButtonPart)
|
|
{
|
|
for (which=0;which<phcLimit;which++) if (Controls[which]==button) break;
|
|
|
|
switch(which)
|
|
{
|
|
case phcOkButton: PerformQuery(genericLookup,nil,false,true); break;
|
|
case phcFingerButton: PerformQuery(fingerLookup,nil,false,true); break;
|
|
case phcToButton: InsertPhAddress(TO_HEAD,modifiers); break;
|
|
case phcCcButton: InsertPhAddress(CC_HEAD,modifiers); break;
|
|
case phcBccButton: InsertPhAddress(BCC_HEAD,modifiers); break;
|
|
}
|
|
Win->hasSelection = MyWinHasSelection(win);
|
|
PhSetGreys();
|
|
}
|
|
|
|
for (which=0;which<phcLimit;which++) if (Controls[which]==button) break;
|
|
AuditHit((modifiers&shiftKey)!=0, (modifiers&controlKey)!=0, (modifiers&optionKey)!=0, (modifiers&cmdKey)!=0, false, GetWindowKind(winWP), AUDITCONTROLID(GetWindowKind(winWP),which), mouseDown);
|
|
|
|
}
|
|
|
|
/**********************************************************************
|
|
* InsertPhAddress - insert addresses from the ph window
|
|
**********************************************************************/
|
|
OSErr InsertPhAddress(short txeIndex,short modifiers)
|
|
{
|
|
OSErr err=fnfErr;
|
|
UserEntryHandle ueh;
|
|
long start;
|
|
HeadSpec hs;
|
|
|
|
MyWindowPtr win = TopCompositionWindow(true, false);
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
|
|
if (!win)
|
|
err = fnfErr;
|
|
else
|
|
{
|
|
if (GetWindowKind(winWP)==COMP_WIN && CompHeadFind(Win2MessH(win),txeIndex,&hs))
|
|
PetePrepareUndo(win->pte,peUndoPaste,hs.stop,hs.stop,&start,nil);
|
|
else
|
|
PetePrepareUndo(win->pte,peUndoPaste,-1,-1,&start,nil);
|
|
for (ueh=UserList;ueh;ueh = (*ueh)->next)
|
|
if (UEHIsSelected(ueh))
|
|
{
|
|
err = InsertAddress(win,txeIndex,LDRef(ueh)->address);
|
|
UL(ueh);
|
|
if (err) break;
|
|
}
|
|
PeteFinishUndo(win->pte,peUndoPaste,start,-1);
|
|
|
|
if (!IsWindowVisible(winWP))
|
|
{
|
|
win->isDirty = False;
|
|
}
|
|
ShowMyWindow(winWP);
|
|
if (!(modifiers&(cmdKey|shiftKey|optionKey))) UserSelectWindow(winWP);
|
|
}
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* InsertAddress - insert an address in a text field
|
|
**********************************************************************/
|
|
OSErr InsertAddress(MyWindowPtr win,short txeIndex,PStr address)
|
|
{
|
|
HeadSpec hs;
|
|
MessHandle messH = Win2MessH(win);
|
|
|
|
PushGWorld();
|
|
SetPort_(GetMyWindowCGrafPtr(win));
|
|
|
|
if (CompHeadFind(messH,txeIndex,&hs))
|
|
{
|
|
InsertCommaIfNeedBe(TheBody,&hs);
|
|
CompHeadAppendStr(TheBody,&hs,address);
|
|
PeteSelect(win,TheBody,hs.stop,hs.stop);
|
|
if (!PrefIsSet(PREF_NICK_CACHE))
|
|
CacheRecentNickname(address);
|
|
}
|
|
PopGWorld();
|
|
return(noErr);
|
|
}
|
|
|
|
#ifdef TWO
|
|
/************************************************************************
|
|
*
|
|
************************************************************************/
|
|
void SetPhTablePref(ControlHandle c,short pref)
|
|
{
|
|
short item = GetControlValue(c);
|
|
short id=0;
|
|
Str63 scratch;
|
|
OSType type;
|
|
Handle res;
|
|
|
|
if (item>1)
|
|
{
|
|
MyGetItem(Control2Menu(c),item,scratch);
|
|
if (res=GetNamedResource('taBL',scratch))
|
|
GetResInfo(res,&id,&type,scratch);
|
|
}
|
|
|
|
NumToString(id,scratch);
|
|
SetPref(pref,scratch);
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************
|
|
* PhClick - handle a click in the ph window
|
|
************************************************************************/
|
|
void PhClick(MyWindowPtr win, EventRecord *event)
|
|
{
|
|
Point mouse = event->where;
|
|
PETEHandle pte = nil;
|
|
|
|
GlobalToLocal(&mouse);
|
|
|
|
if (PtInPETE(mouse,QPTE))
|
|
pte = QPTE;
|
|
else if (PtInPETE(mouse,APTE))
|
|
pte = APTE;
|
|
|
|
if (PeteIsValid(pte))
|
|
{
|
|
if (PeteEdit(win,pte,peeEvent,(void*)event)==tsmDocNotActiveErr)
|
|
{
|
|
PhFocus(pte);
|
|
PeteEdit(win,pte,peeEvent,(void*)event);
|
|
}
|
|
if (event->modifiers&cmdKey && !URL)
|
|
{
|
|
PhSetGreys();
|
|
if (CanAddress()) PhButton(win,Controls[Outlined],event->modifiers,kControlButtonPart);
|
|
}
|
|
}
|
|
else HandleControl(mouse,win);
|
|
|
|
win->hasSelection = MyWinHasSelection(win);
|
|
PhSetGreys();
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhApp1 - handle an app1 event
|
|
************************************************************************/
|
|
Boolean PhApp1(MyWindowPtr win, EventRecord *event)
|
|
{
|
|
event->what = keyDown;
|
|
PeteEdit(win,APTE,peeEvent,(void*)event);
|
|
return(True);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhKey - keystrokes in the ph window
|
|
************************************************************************/
|
|
Boolean PhKey(MyWindowPtr win, EventRecord *event)
|
|
{
|
|
short key = event->message & 0xff;
|
|
UserEntryHandle ueh;
|
|
long start,end;
|
|
|
|
if (event->modifiers & cmdKey) {return(False);} /* no command keys! */
|
|
|
|
if (key==returnChar || key==enterChar)
|
|
{
|
|
//Undo.didClick = True;
|
|
if (Outlined>=0)
|
|
{
|
|
if (!PhURLQuery())
|
|
PhButton(Win,Controls[Outlined],event->modifiers,kControlButtonPart);
|
|
}
|
|
return(True);
|
|
}
|
|
else if (key==tabChar)
|
|
{
|
|
start = 0;
|
|
end = 0x7fffffff;
|
|
if (win->pte==QPTE)
|
|
{
|
|
PhFocus(APTE);
|
|
ueh = UserList;
|
|
if (event->modifiers&shiftKey && ueh) LL_Last(UserList,ueh);
|
|
if (ueh)
|
|
{
|
|
start = (*ueh)->start;
|
|
end = (*ueh)->end;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ueh=UserList;ueh;ueh=(*ueh)->next)
|
|
if (UEHIsSelected(ueh)) break;
|
|
if (ueh && event->modifiers&shiftKey)
|
|
if (ueh!=UserList)
|
|
{
|
|
UserEntryHandle curUEH = ueh;
|
|
LL_Parent(UserList,curUEH,ueh);
|
|
}
|
|
else ueh = nil;
|
|
else
|
|
for (;ueh;ueh=(*ueh)->next)
|
|
if (!UEHIsSelected(ueh)) break;
|
|
if (ueh)
|
|
{
|
|
start = (*ueh)->start;
|
|
end = (*ueh)->end;
|
|
}
|
|
else PhFocus(QPTE);
|
|
}
|
|
|
|
PeteSelect(nil,win->pte,start,end);
|
|
PeteScroll(win->pte,pseNoScroll,pseCenterSelection);
|
|
}
|
|
else if (win->ro && DirtyKey(key))
|
|
{
|
|
PhFocus(QPTE);
|
|
PeteSelect(nil,QPTE,0,REAL_BIG);
|
|
}
|
|
|
|
if (key!=tabChar) PeteEdit(win,win->pte,peeEvent,(void*)event);
|
|
|
|
Win->hasSelection = MyWinHasSelection(win);
|
|
PhSetGreys();
|
|
|
|
return(True);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CurQueryTextIsURL - returns true if beginning of query text might
|
|
* be a URL
|
|
**********************************************************************/
|
|
Boolean CurQueryTextIsURL(void)
|
|
{
|
|
Str255 query;
|
|
UPtr curSpot;
|
|
Str255 proto;
|
|
Str255 scratch;
|
|
|
|
|
|
PeteSString(query,QPTE);
|
|
if (!*query)
|
|
return false;
|
|
curSpot = query + 1;
|
|
|
|
if (!PToken(query,proto,&curSpot,":") || (curSpot[-1] != ':'))
|
|
return false;
|
|
if (!PToken(query,scratch,&curSpot,"/") || (curSpot[-1] != '/'))
|
|
return false;
|
|
if (!FindSTRNIndex(ProtocolStrn,proto))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhURLQuery - if the query is a url, execute it
|
|
**********************************************************************/
|
|
Boolean PhURLQuery(void)
|
|
{
|
|
Str255 query;
|
|
Boolean result;
|
|
|
|
PeteSString(query,QPTE);
|
|
SelfURL = True;
|
|
result = (!ParseURL(query,nil,nil,nil) && !OpenLocalURL(query,nil));
|
|
SelfURL = False;
|
|
return(result);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhMenu - menu selections in the ph window
|
|
************************************************************************/
|
|
Boolean PhMenu(MyWindowPtr win, int menu, int item, short modifiers)
|
|
{
|
|
#pragma unused(modifiers)
|
|
PETEHandle pte;
|
|
|
|
switch (menu)
|
|
{
|
|
case FILE_MENU:
|
|
switch(item)
|
|
{
|
|
case FILE_PRINT_ITEM:
|
|
case FILE_PRINT_ONE_ITEM:
|
|
{
|
|
pte = Win->pte;
|
|
PhFocus(APTE);
|
|
PrintOneMessage(win,modifiers&shiftKey,item==FILE_PRINT_ONE_ITEM);
|
|
PhFocus(pte);
|
|
return(True);
|
|
}
|
|
}
|
|
break;
|
|
case EDIT_MENU:
|
|
switch (item)
|
|
{
|
|
case EDIT_FINISH_ITEM:
|
|
return(False);
|
|
break;
|
|
default:
|
|
if ((item==EDIT_PASTE_ITEM || item==EDIT_QUOTE_ITEM) && win->ro)
|
|
{
|
|
PhFocus(QPTE);
|
|
PeteSelect(nil,QPTE,0,REAL_BIG);
|
|
}
|
|
return(TextMenu(Win,menu,item,modifiers));
|
|
break;
|
|
}
|
|
break;
|
|
case SPECIAL_MENU:
|
|
switch (AdjustSpecialMenuSelection(item))
|
|
{
|
|
case SPECIAL_MAKE_NICK_ITEM:
|
|
PhMakeNick();
|
|
return(True);
|
|
break;
|
|
}
|
|
}
|
|
return(False);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhMakeNick - make a nickname from a ph entry
|
|
**********************************************************************/
|
|
OSErr PhMakeNick(void)
|
|
{
|
|
UserEntryHandle ueh;
|
|
Str255 address, shortAddr;
|
|
Handle addresses = NuHandle(0);
|
|
OSErr err = fnfErr;
|
|
Boolean uncomma = PrefIsSet(PREF_UNCOMMA);
|
|
|
|
if (!addresses) return(WarnUser(MEM_ERR,MemError()));
|
|
|
|
if (uncomma) SetPref(PREF_UNCOMMA,NoStr);
|
|
/*
|
|
* gather the selected addresses
|
|
*/
|
|
for (ueh=UserList;ueh;ueh = (*ueh)->next)
|
|
{
|
|
if (UEHIsSelected(ueh))
|
|
{
|
|
PCopy(address,(*ueh)->address);
|
|
ShortAddr(shortAddr,address);
|
|
CanonAddr(address,shortAddr,(LDRef(ueh))->name);
|
|
UL(ueh);
|
|
address[*address+1] = 0;
|
|
err = PtrPlusHand_(address,addresses,*address+2);
|
|
if (err) break;
|
|
}
|
|
}
|
|
if (uncomma) SetPref(PREF_UNCOMMA,YesStr);
|
|
if (!err) err = PtrPlusHand_("",addresses,1);
|
|
if (err)
|
|
{
|
|
ZapHandle(addresses);
|
|
return(WarnUser(MEM_ERR,err));
|
|
}
|
|
|
|
/*
|
|
* make the nickname
|
|
*/
|
|
#ifdef VCARD
|
|
NewNick(addresses,nil,0);
|
|
#else
|
|
NewNick(addresses,0);
|
|
#endif
|
|
|
|
return(noErr);
|
|
}
|
|
|
|
|
|
void InvalPhWindowTop(void)
|
|
|
|
{
|
|
GrafPtr origPort;
|
|
Rect r;
|
|
|
|
|
|
r = Win->contR;
|
|
r.bottom = QRect.top;
|
|
|
|
GetPort(&origPort);
|
|
SetPort(GetMyWindowCGrafPtr(Win));
|
|
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
|
|
SetPort(origPort);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* PhUpdate - update the ph window
|
|
************************************************************************/
|
|
void PhUpdate(MyWindowPtr win)
|
|
{
|
|
#pragma unused(win)
|
|
Rect r;
|
|
Str255 scratch;
|
|
|
|
r = QRect;
|
|
MoveTo(r.left,r.top - 6);
|
|
PCopy(scratch,Label);
|
|
SetSmallSysFont();
|
|
DrawString(scratch);
|
|
|
|
if (Outlined>=0) OutlineControl(Controls[Outlined],true);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhDidResize - handle resizing of the ph window
|
|
************************************************************************/
|
|
void PhDidResize(MyWindowPtr win, Rect *oldContR)
|
|
{
|
|
#pragma unused(win,oldContR)
|
|
Rect r,rOK,rFinger,rListButton;
|
|
Point p;
|
|
short hi;
|
|
short wi;
|
|
short aquaAdjustment = 0;
|
|
|
|
// the Finger and Lookup buttons are bigger under OSX
|
|
if (HaveOSX()) aquaAdjustment = 2;
|
|
|
|
GetControlBounds(OkButton,&rOK);
|
|
hi = rOK.bottom - rOK.top;
|
|
wi = rOK.right - rOK.left;
|
|
|
|
/*
|
|
* put the Lookup and Finger buttons in the right place
|
|
*/
|
|
p.h = Win->contR.right - GROW_SIZE - wi;
|
|
p.v = Win->contR.top + GROW_SIZE/2 + 3*aquaAdjustment;
|
|
OFFSET_RECT(&rOK,p.h-rOK.left,p.v-rOK.top);
|
|
SetControlBounds(OkButton,&rOK);
|
|
p.h -= INSET + wi;
|
|
GetControlBounds(FingerButton,&rFinger);
|
|
OFFSET_RECT(&rFinger,p.h-rFinger.left,p.v-rFinger.top);
|
|
SetControlBounds(FingerButton,&rFinger);
|
|
|
|
/*
|
|
* position the server list button
|
|
*/
|
|
GetControlBounds(OkButton,&r);
|
|
r.left = r.right - (r.bottom - r.top);
|
|
OffsetRect(&r, 0, RectHi(r) + GROW_SIZE/2);
|
|
MoveMyCntl(ListButton,r.left,r.top+aquaAdjustment,16,16);
|
|
|
|
/*
|
|
* calculate the frame for the command box
|
|
*/
|
|
r = Win->contR;
|
|
GetControlBounds(ListButton,&rListButton);
|
|
r.top = rListButton.top+2;
|
|
r.bottom = r.top + ONE_LINE_HI(Win);
|
|
//OffsetRect(&r,0,-(hi-r.bottom+r.top)/2);
|
|
r.left += GROW_SIZE;
|
|
r.right = rListButton.left - GROW_SIZE/2;
|
|
InsetRect(&r,3,0);
|
|
QRect = r;
|
|
|
|
/*
|
|
* calculate the frame for the answer box
|
|
*/
|
|
r.top = rListButton.bottom + 2*GROW_SIZE/3;
|
|
r.bottom = win->contR.bottom;
|
|
r.right = win->contR.right - GROW_SIZE+1;
|
|
r.bottom -= 3*INSET + ControlHi(ToButton);
|
|
if (XlOutControl) r.bottom -= ControlHi(XlOutControl)+2*INSET;
|
|
r.right -= 3;
|
|
ARect = r;
|
|
|
|
/*
|
|
* now for the TE's
|
|
*/
|
|
r = QRect;
|
|
PeteDidResize(QPTE,&r);
|
|
r = ARect;
|
|
PeteDidResize(APTE,&r);
|
|
|
|
/*
|
|
* To, Cc, Bcc
|
|
*/
|
|
hi = ControlHi(ToButton);
|
|
wi = (r.right-r.left)/3 - 4*INSET;
|
|
MoveMyCntl(ToButton,r.left,r.bottom+3*INSET/2,wi,hi);
|
|
MoveMyCntl(BccButton,r.right-wi-INSET,r.bottom+3*INSET/2,wi,hi);
|
|
MoveMyCntl(CcButton,(r.right+r.left-wi-INSET)/2,r.bottom+3*INSET/2,wi,hi);
|
|
|
|
/*
|
|
* xlit controls?
|
|
*/
|
|
if (XlOutControl)
|
|
{
|
|
wi = ControlWi(XlOutControl);
|
|
hi = ControlHi(XlOutControl);
|
|
MoveMyCntl(XlOutControl,(r.right+r.left)/2-INSET-wi,win->contR.bottom-hi-INSET,wi,hi);
|
|
MoveMyCntl(XlInControl,r.right-INSET-wi,win->contR.bottom-hi-INSET,wi,hi);
|
|
}
|
|
InvalWindowRect(GetMyWindowWindowPtr(win),&win->contR);
|
|
}
|
|
|
|
#pragma segment Main
|
|
/************************************************************************
|
|
* PhClose - close the ph window
|
|
************************************************************************/
|
|
Boolean PhClose(MyWindowPtr win)
|
|
{
|
|
#pragma unused(win)
|
|
if (PhGlobals)
|
|
{
|
|
PhKill();
|
|
LockPhGlobals();
|
|
ZapTransStream(&PhStream);
|
|
if (SiteInfo) ZapHandle(SiteInfo);
|
|
ZapUserList();
|
|
ZapHandle(PhGlobals);
|
|
PhGlobals = nil;
|
|
}
|
|
return(True);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ZapUserList - kill the user list
|
|
**********************************************************************/
|
|
void ZapUserList(void)
|
|
{
|
|
UserEntryHandle ueh;
|
|
|
|
for (ueh=UserList;ueh;ueh=UserList)
|
|
{
|
|
LL_Remove(UserList,ueh,(UserEntryHandle));
|
|
ZapFields((*ueh)->fields);
|
|
ZapHandle((*ueh)->fields);
|
|
ZapHandle(ueh);
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ZapFields - zap a list of fields
|
|
**********************************************************************/
|
|
void ZapFields(UHandle **fields)
|
|
{
|
|
short i;
|
|
|
|
if (fields)
|
|
{
|
|
for (i=HandleCount(fields);i--;)
|
|
ZapHandle((*fields)[i]);
|
|
}
|
|
}
|
|
|
|
|
|
/* FINISH *//* should we do a #pragma segment LDAP here? */
|
|
|
|
void FormatLDAPEmailAddr(Str255 userName, Str255 emailAddr, Str255 combinedStr)
|
|
{
|
|
if (userName[0] && emailAddr[0])
|
|
CanonAddr(combinedStr,emailAddr,userName);
|
|
else
|
|
PCopy(combinedStr, emailAddr);
|
|
}
|
|
|
|
|
|
void LDAPEntryFilter(LDAPSessionHdl ldapSession, Str255 userNameStr, Str255 emailAddressStr, long startOffset, long endOffset)
|
|
|
|
{
|
|
UserEntryHandle userEntryHdl;
|
|
UserEntryPtr entryPtr;
|
|
long len;
|
|
#pragma unused (ldapSession)
|
|
|
|
|
|
userEntryHdl = NewZH(UserEntry);
|
|
if (!userEntryHdl)
|
|
return;
|
|
|
|
entryPtr = LDRef(userEntryHdl);
|
|
|
|
FormatLDAPEmailAddr(userNameStr, emailAddressStr, entryPtr->address);
|
|
|
|
len = userNameStr[0];
|
|
if (len > 63)
|
|
len = 63;
|
|
BlockMoveData(userNameStr, entryPtr->name, len + 1);
|
|
entryPtr->name[0] = len;
|
|
|
|
entryPtr->start = startOffset;
|
|
entryPtr->end = endOffset;
|
|
|
|
entryPtr->fields = NewZH(UHandle);
|
|
|
|
UL(userEntryHdl);
|
|
|
|
LL_Queue(UserList, userEntryHdl, (UserEntryHandle));
|
|
}
|
|
|
|
|
|
OSErr OutputStrToAnswerField(Str255 theString)
|
|
|
|
{
|
|
OSErr err;
|
|
Handle textHdl;
|
|
long textLen;
|
|
|
|
|
|
if (!*theString)
|
|
{
|
|
PeteSetTextPtr(APTE, nil, 0);
|
|
return noErr;
|
|
}
|
|
|
|
textLen = theString[0] + 1; /* add one to accomodate a CR at the end */
|
|
textHdl = NewHandle(textLen);
|
|
if (!textHdl)
|
|
return MemError();
|
|
BlockMoveData(theString + 1, *textHdl, theString[0]);
|
|
*(*textHdl + theString[0]) = 0x0D;
|
|
err = PeteSetText(APTE, textHdl);
|
|
DisposeHandle(textHdl);
|
|
return err;
|
|
}
|
|
|
|
|
|
OSErr OutputStrIndexToAnswerField(short strIndex)
|
|
|
|
{
|
|
Str255 theString;
|
|
|
|
|
|
GetRString(theString, strIndex);
|
|
return OutputStrToAnswerField(theString);
|
|
}
|
|
|
|
|
|
#ifdef LDAP_ENABLED
|
|
OSErr OutputLDAPErrorMessage(Str255 errorStr, OSErr errCode, Boolean translateLDAPErrCodes)
|
|
|
|
{
|
|
OSErr err;
|
|
Handle errorText;
|
|
long textLen;
|
|
Str255 errCodeStr;
|
|
|
|
|
|
textLen = errorStr[0] + 1; /* add one to accomodate a CR at the end */
|
|
if (errCode)
|
|
{
|
|
if (translateLDAPErrCodes)
|
|
{
|
|
err = LDAPErrCodeToMsgStr(errCode, errCodeStr, true);
|
|
if (err)
|
|
NumToString(errCode, errCodeStr);
|
|
}
|
|
else
|
|
NumToString(errCode, errCodeStr);
|
|
textLen += errCodeStr[0];
|
|
}
|
|
errorText = NewHandle(textLen);
|
|
if (!errorText)
|
|
return MemError();
|
|
BlockMoveData(errorStr + 1, *errorText, errorStr[0]);
|
|
if (errCode)
|
|
{
|
|
BlockMoveData(errCodeStr + 1, *errorText + errorStr[0], errCodeStr[0]);
|
|
*(*errorText + errorStr[0] + errCodeStr[0]) = 0x0D;
|
|
}
|
|
else
|
|
*(*errorText + errorStr[0]) = 0x0D;
|
|
|
|
err = PeteSetText(APTE, errorText);
|
|
|
|
DisposeHandle(errorText);
|
|
return err;
|
|
}
|
|
|
|
|
|
OSErr ReportLDAPSearchResults(LDAPSessionHdl ldapSession)
|
|
|
|
{
|
|
OSErr err;
|
|
Handle resultText;
|
|
|
|
|
|
err = LDAPResultsToText(ldapSession, &resultText, LDAPAttrList, !PrefIsSet(PREF_LDAP_NO_LABEL_TRANS), LDAPEntryFilter);
|
|
if (err)
|
|
return err;
|
|
|
|
err = PeteSetText(APTE, resultText);
|
|
|
|
DisposeHandle(resultText);
|
|
return err;
|
|
}
|
|
#endif //ifndef LDAP_ENABLED
|
|
|
|
|
|
#if 0
|
|
/* FINISH *//* REMOVE */
|
|
OSErr PrepLDAPLookup(Str255 queryStr, Boolean cmdIsURLQuery, Str255 ldapServer, long *ldapPortNo, Boolean *useRawSearchStr, short *searchScope, Str255 searchBaseObject, LDAPAttrListHdl *attributesList, LDAPAttrListHdl *attrListToKill)
|
|
|
|
{
|
|
#ifdef LDAP_ENABLED
|
|
|
|
OSErr err;
|
|
Str255 urlProtocolStr, urlHostStr;
|
|
Str255 urlQueryStr;
|
|
Str255 searchFilter;
|
|
ProtocolEnum protocolType;
|
|
DirSvcLookupType lookupType;
|
|
short urlPort;
|
|
#pragma unused (attrListToKill)
|
|
|
|
|
|
*useRawSearchStr = (queryStr[0] && (queryStr[1] == '('));
|
|
*searchScope = LDAP_SCOPE_SUBTREE;
|
|
searchBaseObject[0] = 0;
|
|
*attributesList = nil;
|
|
|
|
if (!queryStr)
|
|
return noErr;
|
|
|
|
if (cmdIsURLQuery)
|
|
BlockMoveData(queryStr, urlQueryStr, queryStr[0] + 1);
|
|
else
|
|
{
|
|
err = ParseURL(queryStr, urlProtocolStr, urlHostStr, urlQueryStr);
|
|
if (err)
|
|
return noErr;
|
|
protocolType = FindSTRNIndex(ProtocolStrn, urlProtocolStr);
|
|
lookupType = ProtocolToDirSvcType(protocolType);
|
|
if (lookupType != ldapLookup)
|
|
return noErr;
|
|
}
|
|
|
|
err = ParseLDAPURLQuery(urlQueryStr, searchBaseObject, attributesList, searchScope, searchFilter);
|
|
if (err)
|
|
return err;
|
|
|
|
FixURLString(urlHostStr);
|
|
if (ParsePortFromHost(urlHostStr, urlHostStr, &urlPort))
|
|
{
|
|
BlockMoveData(urlHostStr, ldapServer, urlHostStr[0] + 1);
|
|
*ldapPortNo = urlPort;
|
|
}
|
|
|
|
BlockMoveData(searchFilter, queryStr, searchFilter[0] + 1);
|
|
*useRawSearchStr = true;
|
|
return noErr;
|
|
|
|
#else //ifdef LDAP_ENABLED
|
|
|
|
#pragma unused (ldapServer, ldapPortNo, queryStr, cmdIsURLQuery, useRawSearchStr, searchScope, searchBaseObject, attributesList)
|
|
|
|
return paramErr;
|
|
|
|
#endif //ifdef LDAP_ENABLED
|
|
}
|
|
#endif
|
|
|
|
|
|
OSErr DoLDAPLookup(Str255 ldapServer, int ldapPortNo, Str255 queryStr, Boolean queryStrIsURLQuery)
|
|
|
|
{
|
|
#ifdef LDAP_ENABLED
|
|
OSErr err, scratchErr;
|
|
short errStrIndex;
|
|
LDAPSessionHdl ldapSession;
|
|
Str255 errorStr;
|
|
Str255 searchStr;
|
|
Boolean useRawSearchStr;
|
|
short searchScope;
|
|
Str255 searchBaseObject;
|
|
LDAPAttrListHdl attributesList;
|
|
UPtr forHost = errorStr;
|
|
|
|
|
|
if (!ldapServer[0] || !queryStr[0])
|
|
return noErr;
|
|
|
|
if (!LDAPSupportPresent())
|
|
{
|
|
err = LDAPSupportError();
|
|
errStrIndex = GetLDAPSpecialErrMsgIndex(err);
|
|
if (!errStrIndex)
|
|
errStrIndex = LDAP_NOT_SUPPORTED_MSG;
|
|
else
|
|
err = noErr;
|
|
GetRString(errorStr, errStrIndex);
|
|
scratchErr = OutputLDAPErrorMessage(errorStr, err, false);
|
|
return noErr;
|
|
}
|
|
|
|
err = LoadLDAPCode();
|
|
if (err)
|
|
{
|
|
errStrIndex = GetLDAPSpecialErrMsgIndex(err);
|
|
if (!errStrIndex)
|
|
errStrIndex = LDAP_LIB_OPEN_ERR_MSG;
|
|
else
|
|
err = noErr;
|
|
GetRString(errorStr, errStrIndex);
|
|
scratchErr = OutputLDAPErrorMessage(errorStr, err, false);
|
|
return err;
|
|
}
|
|
|
|
err = VerifyDirSvcHost(ldapServer, ldapPortNo);
|
|
if (err)
|
|
{
|
|
scratchErr = OutputStrIndexToAnswerField(DIR_SVC_SERVER_RESOLVE_ERR_MSG);
|
|
goto Exit1;
|
|
}
|
|
|
|
err = NewLDAPSession(&ldapSession);
|
|
if (err)
|
|
{
|
|
if (err == memFullErr)
|
|
{
|
|
GetRString(errorStr, LDAP_OPEN_MEM_ERR_MSG);
|
|
scratchErr = OutputLDAPErrorMessage(errorStr, noErr, false);
|
|
}
|
|
else
|
|
{
|
|
GetRString(errorStr, LDAP_OPEN_ERR_MSG);
|
|
scratchErr = OutputLDAPErrorMessage(errorStr, err, true);
|
|
}
|
|
goto Exit1;
|
|
}
|
|
|
|
err = OpenLDAPSession(ldapSession, ldapServer, ldapPortNo);
|
|
if (err)
|
|
{
|
|
if (err == memFullErr)
|
|
{
|
|
GetRString(errorStr, LDAP_OPEN_MEM_ERR_MSG);
|
|
scratchErr = OutputLDAPErrorMessage(errorStr, noErr, false);
|
|
}
|
|
else
|
|
{
|
|
GetRString(errorStr, LDAP_OPEN_ERR_MSG);
|
|
scratchErr = OutputLDAPErrorMessage(errorStr, err, true);
|
|
}
|
|
goto Exit2;
|
|
}
|
|
|
|
if (!GetLDAPServerGlobals(forHost, nil, &searchScope, searchBaseObject, &attributesList))
|
|
{
|
|
scratchErr = OutputStrIndexToAnswerField(DIR_SVC_SERVER_RESOLVE_ERR_MSG);
|
|
err = noErr;
|
|
goto Exit3;
|
|
}
|
|
if (!searchBaseObject[0] && PrefIsSet(PREF_LDAP_REQUIRE_BASE_OBJECT))
|
|
{
|
|
scratchErr = OutputStrIndexToAnswerField(LDAP_SEARCH_REQUIRES_BASE_OBJECT);
|
|
err = noErr;
|
|
goto Exit3;
|
|
}
|
|
|
|
if (queryStrIsURLQuery)
|
|
{
|
|
useRawSearchStr = true;
|
|
scratchErr = ParseLDAPURLQuery(queryStr, nil, nil, nil, searchStr); /* ignore errors */
|
|
}
|
|
else
|
|
{
|
|
BlockMoveData(queryStr, searchStr, queryStr[0] + 1);
|
|
useRawSearchStr = (searchStr[0] && (searchStr[1] == '('));
|
|
}
|
|
|
|
err = LDAPSearch(ldapSession, searchStr, forHost, useRawSearchStr, searchScope, searchBaseObject, attributesList);
|
|
scratchErr = ReportLDAPSearchResults(ldapSession);
|
|
SFWTC = true; // we don't trust ldap.
|
|
if (!err)
|
|
err = scratchErr;
|
|
scratchErr = ClearLDAPSearchResults(ldapSession);
|
|
if (!err)
|
|
err = scratchErr;
|
|
if (err)
|
|
goto Exit3;
|
|
|
|
|
|
Exit3:
|
|
scratchErr = CloseLDAPSession(ldapSession);
|
|
if (!err)
|
|
err = scratchErr;
|
|
Exit2:
|
|
scratchErr = DisposeLDAPSession(ldapSession);
|
|
if (!err)
|
|
err = scratchErr;
|
|
Exit1:
|
|
scratchErr = UnloadLDAPCode();
|
|
if (!err)
|
|
err = scratchErr;
|
|
Exit0:
|
|
return err;
|
|
|
|
#else //ifdef LDAP_ENABLED
|
|
|
|
return paramErr;
|
|
#endif //ifdef LDAP_ENABLED
|
|
}
|
|
|
|
|
|
#pragma segment Ph
|
|
|
|
/************************************************************************
|
|
* PerformQuery - perform a ph query
|
|
************************************************************************/
|
|
void PerformQuery(DirSvcLookupType lookupType,PStr withCommand, Boolean cmdIsURLQuery, Boolean emptyFirst)
|
|
{
|
|
WindowPtr WinWP = GetMyWindowWindowPtr(Win);
|
|
Str255 cmd;
|
|
Str255 ph;
|
|
Handle table=nil;
|
|
short inId,outId;
|
|
OSErr scratchErr;
|
|
Str255 serverHost;
|
|
long serverPort;
|
|
|
|
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
case fingerLookup:
|
|
case ldapLookup:
|
|
case genericLookup:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (Offline && GoOnline()) return;
|
|
|
|
ZapUserList();
|
|
|
|
SwitchDirSvcType(lookupType);
|
|
|
|
if (lookupType == genericLookup || lookupType == ldapLookup)
|
|
if (!GetDirSvcServerGlobals(&lookupType, serverHost, &serverPort)) /* FINISH *//* do something different - we don't need host & port info */
|
|
{
|
|
scratchErr = OutputStrIndexToAnswerField(DIR_SVC_SERVER_RESOLVE_ERR_MSG);
|
|
return;
|
|
}
|
|
|
|
PhFocus(QPTE);
|
|
if (!withCommand) PeteSelectAll(Win,QPTE);
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
MyGetItem(GetMHandle(WINDOW_MENU),WIN_PH_ITEM,ph);
|
|
break;
|
|
case fingerLookup:
|
|
GetRString(ph,FINGER);
|
|
break;
|
|
case ldapLookup:
|
|
GetRString(ph,LDAP_NAME);
|
|
break;
|
|
}
|
|
|
|
if (lookupType != phLookup) PhKill();
|
|
|
|
if (!withCommand && !*PeteSString(cmd,QPTE))
|
|
{
|
|
SetWTitle_(WinWP,ph);
|
|
LockPhGlobals();
|
|
ZapTransStream(&PhStream);
|
|
UnlockPhGlobals();
|
|
return;
|
|
}
|
|
if (withCommand) PCopy(cmd,withCommand);
|
|
else PeteSString(cmd,QPTE);
|
|
PCatC(ph,':');
|
|
PCat(ph,cmd);
|
|
SetWTitle_(WinWP,ph);
|
|
if (emptyFirst) PeteSetTextPtr(APTE,nil,0);
|
|
|
|
/*
|
|
* install translation tables
|
|
*/
|
|
if (NewTables)
|
|
{
|
|
#ifdef TWO
|
|
inId = GetPrefLong(PREF_PH_IN);
|
|
outId = GetPrefLong(PREF_PH_OUT);
|
|
#else
|
|
inId = GetPrefLong(PREF_IN_XLATE);
|
|
outId = GetPrefLong(PREF_OUT_XLATE);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
inId = TRANS_IN_TABL;
|
|
outId = TransOutTablID();
|
|
}
|
|
if (inId && (table=GetResource_('taBL',inId)))
|
|
{
|
|
HNoPurge_(table);
|
|
if (TransIn = NuPtr(256)) BMD(*table,TransIn,256);
|
|
HPurge(table);
|
|
}
|
|
if (outId && (table=GetResource_('taBL',outId)))
|
|
{
|
|
HNoPurge_(table);
|
|
if (TransOut = NuPtr(256)) BMD(*table,TransOut,256);
|
|
HPurge(table);
|
|
}
|
|
|
|
/*
|
|
* do it
|
|
*/
|
|
InitCursor();
|
|
SetMyCursor(watchCursor);
|
|
|
|
#ifdef CTB
|
|
if (!UseCTB || !DialThePhone(PhStream))
|
|
#endif
|
|
{
|
|
if (TransOut) TransLit(cmd+1,*cmd,TransOut);
|
|
switch (lookupType)
|
|
{
|
|
case phLookup:
|
|
scratchErr = ContactQi(PhStream);
|
|
if (scratchErr==noErr)
|
|
{
|
|
if (!UpdateSiteInfo(PhStream) && !SendQiCommand(PhStream,cmd))
|
|
if (EqualStrRes(cmd,PhStrn+phfServerList)) PhListResponse(PhStream,emptyFirst);
|
|
else GetQiResponse(PhStream,cmd);
|
|
UpdateMyWindow(WinWP);
|
|
if (!Live) CloseQi(PhStream);
|
|
}
|
|
else PhListConnectError(scratchErr); // report Ph connection errors
|
|
break;
|
|
case fingerLookup:
|
|
DoFinger(PhStream, cmd);
|
|
break;
|
|
case ldapLookup:
|
|
scratchErr = DoLDAPLookup(serverHost, serverPort, cmd, cmdIsURLQuery);
|
|
break;
|
|
}
|
|
if (!Live) DestroyTrans(PhStream);
|
|
PeteLock(APTE,0,0x7fffffff,peModLock);
|
|
}
|
|
|
|
#ifdef CTB
|
|
if (UseCTB && !Live) HangUpThePhone();
|
|
#endif
|
|
|
|
/*
|
|
* clean up tables
|
|
*/
|
|
if (TransIn) {ZapPtr(TransIn);TransIn=nil;}
|
|
if (TransOut) {ZapPtr(TransOut);TransOut=nil;}
|
|
|
|
/*
|
|
* set flags
|
|
*/
|
|
Win->hasSelection = MyWinHasSelection(Win);
|
|
PhSetGreys();
|
|
|
|
inId = PeteIsDirty(QPTE);
|
|
LastDirty = inId;
|
|
QueryTicks = TickCount();
|
|
}
|
|
|
|
/**********************************************************************
|
|
* UpdateSiteInfo - update the siteinfo information from the ph server
|
|
**********************************************************************/
|
|
OSErr UpdateSiteInfo(TransStream stream)
|
|
{
|
|
Str255 scratch;
|
|
Str63 data;
|
|
AAHandle grumble;
|
|
short code;
|
|
Byte colon[2];
|
|
long size;
|
|
UPtr spot;
|
|
Str31 key;
|
|
|
|
colon[0] = ':';
|
|
colon[1] = 0;
|
|
|
|
if (!GetPhServerGlobals(scratch, nil))
|
|
return paramErr;
|
|
|
|
/*
|
|
* fetch the info?
|
|
*/
|
|
if (!SiteInfo || AAFetchResData(SiteInfo,PhStrn+phfServerName,data) || !StringSame(scratch,data))
|
|
{
|
|
ZapHandle(SiteInfo);
|
|
grumble = AANew(32,64);
|
|
SiteInfo = grumble;
|
|
if (!SiteInfo) return(WarnUser(MEM_ERR,MemError()));
|
|
AAAddResItem(SiteInfo,True,PhStrn+phfServerName,scratch);
|
|
|
|
if (!SendQiCommand(stream,GetRString(scratch,PhStrn+phfSiteInfo)))
|
|
|
|
code = 600;
|
|
for (size=sizeof(scratch)-3;!RecvLine(stream,scratch+1,&size);size=sizeof(scratch)-3)
|
|
{
|
|
size--; /* trim newline */
|
|
*scratch = size;
|
|
scratch[size+1] = 0;
|
|
code = Atoi(scratch+1);
|
|
if (code>=200) break;
|
|
if (-300<code && code <= -200)
|
|
{
|
|
spot = scratch+1;
|
|
PToken(scratch,key,&spot,colon); /* error code */
|
|
PToken(scratch,key,&spot,colon); /* ordinal */
|
|
PToken(scratch,key,&spot,colon); /* capability name */
|
|
PToken(scratch,data,&spot,colon); /* value */
|
|
if (*key && *data && AAAddItem(SiteInfo,True,key,data))
|
|
{
|
|
WarnUser(MEM_ERR,MemError());
|
|
code = 600;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (code>=600)
|
|
{
|
|
ZapHandle(SiteInfo);
|
|
return(fnfErr);
|
|
}
|
|
}
|
|
return(noErr);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ListServers - list the ph servers
|
|
**********************************************************************/
|
|
void PhListServers(void)
|
|
{
|
|
Str31 cmd;
|
|
Str255 newServer;
|
|
#ifdef LDAP_ENABLED
|
|
OSErr err;
|
|
Handle ldapServerList;
|
|
char cr;
|
|
#endif
|
|
Str255 origDirSvcServer;
|
|
DirSvcLookupType origDirSvcType;
|
|
long origDirSvcPort;
|
|
Boolean origDirSvcHostResolved;
|
|
Boolean canDoPhLookup;
|
|
Boolean useFallbackServer;
|
|
Boolean scratch;
|
|
UPtr s = origDirSvcServer; // notational convenience
|
|
short n;
|
|
|
|
// clear it out
|
|
PeteSetTextPtr(APTE,"",0);
|
|
|
|
// first, list our current server
|
|
if (*GetPref(newServer,PREF_PH))
|
|
{
|
|
GetRString(s,CONFIG_DIR_SERVER);
|
|
PeteAppendText(s+1,*s,APTE);
|
|
ComposeRString(s,RECENT_DIR_FMT,newServer);
|
|
PeteAppendText(s+1,*s,APTE);
|
|
PeteAppendText(Cr+1,*Cr,APTE);
|
|
}
|
|
|
|
// next, list recent servers
|
|
if (*GetRString(newServer,RecentDirServStrn+1))
|
|
{
|
|
GetRString(s,RECENT_DIR_SERVERS);
|
|
PeteAppendText(s+1,*s,APTE);
|
|
n = RecentDirServStrn+1;
|
|
do
|
|
{
|
|
URLEscape(newServer);
|
|
ComposeRString(s,RECENT_DIR_FMT,newServer);
|
|
PeteAppendText(s+1,*s,APTE);
|
|
}
|
|
while (*GetRString(newServer,++n));
|
|
PeteAppendText(Cr+1,*Cr,APTE);
|
|
}
|
|
|
|
if (!(MainEvent.modifiers&shiftKey))
|
|
{
|
|
// next, ph servers
|
|
canDoPhLookup = false;
|
|
useFallbackServer = false;
|
|
if (!DirSvcHostResolved)
|
|
scratch = GetDirSvcServerGlobals(nil, nil, nil);
|
|
|
|
// if ph_server_server set, always use it SD
|
|
if (*GetRString(newServer,PH_SERVER_SERVER))
|
|
{
|
|
canDoPhLookup = true;
|
|
useFallbackServer = true;
|
|
}
|
|
// if current server is ph, use that SD
|
|
else if (DirSvcHostResolved && (DirSvcType == phLookup))
|
|
canDoPhLookup = true;
|
|
// if not, fall back to master server SD
|
|
else if (*GetRString(newServer,MASTER_SERVER_SERVER))
|
|
{
|
|
canDoPhLookup = true;
|
|
useFallbackServer = true;
|
|
}
|
|
|
|
if (canDoPhLookup)
|
|
{
|
|
if (useFallbackServer)
|
|
{
|
|
origDirSvcType = DirSvcType;
|
|
PCopy(origDirSvcServer, DirSvcServer);
|
|
origDirSvcPort = DirSvcPort;
|
|
origDirSvcHostResolved = DirSvcHostResolved;
|
|
|
|
DirSvcType = phLookup;
|
|
PCopy(DirSvcServer, newServer);
|
|
DirSvcPort = GetDefaultDirSvcPort(phLookup);
|
|
DirSvcHostResolved = true;
|
|
}
|
|
PerformQuery(phLookup,GetRString(cmd,PhStrn+phfServerList),false,false);
|
|
if (useFallbackServer)
|
|
{
|
|
DirSvcType = origDirSvcType;
|
|
PCopy(DirSvcServer, origDirSvcServer);
|
|
DirSvcPort = origDirSvcPort;
|
|
DirSvcHostResolved = origDirSvcHostResolved;
|
|
|
|
RedisplayPhHost();
|
|
}
|
|
#ifdef LDAP_ENABLED
|
|
PeteAppendText(LDAPDividerStr + 1, *LDAPDividerStr, APTE);
|
|
cr = 13;
|
|
PeteAppendText(&cr, 1, APTE);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef LDAP_ENABLED
|
|
err = GetLDAPServerList(&ldapServerList);
|
|
if (err)
|
|
return;
|
|
err = PeteAppendText(LDRef(ldapServerList), GetHandleSize(ldapServerList), APTE);
|
|
DisposeHandle(ldapServerList);
|
|
#endif
|
|
}
|
|
|
|
/**********************************************************************
|
|
*
|
|
**********************************************************************/
|
|
void PhListResponse(TransStream stream,Boolean emptyFirst)
|
|
{
|
|
Str255 scratch;
|
|
short code;
|
|
Byte colon[2];
|
|
long size;
|
|
UPtr spot;
|
|
Str255 key, name, server;
|
|
|
|
colon[0] = ':';
|
|
colon[1] = 0;
|
|
|
|
if (emptyFirst) PeteSetTextPtr(APTE,nil,0);
|
|
PeteCalcOff(APTE);
|
|
|
|
code = 600;
|
|
for (size=sizeof(scratch)-3;!RecvLine(stream,scratch+1,&size);size=sizeof(scratch)-3)
|
|
{
|
|
size--; /* trim newline */
|
|
*scratch = size;
|
|
scratch[size+1] = 0;
|
|
code = Atoi(scratch+1);
|
|
if (-300<code && code <= -200)
|
|
{
|
|
spot = scratch+1;
|
|
PToken(scratch,key,&spot,colon); /* error code */
|
|
PToken(scratch,key,&spot,colon); /* ordinal */
|
|
PToken(scratch,key,&spot,colon); /* field name */
|
|
PToken(scratch,key,&spot,colon); /* subfield */
|
|
TrimWhite(key);
|
|
TrimInitialWhite(key);
|
|
if (EqualStrRes(key,PhStrn+phfSite))
|
|
MakePStr(name,spot,(scratch+(*scratch+1))-spot);
|
|
else if (EqualStrRes(key,PhStrn+phfServer) && *name)
|
|
{
|
|
MakePStr(server,spot,(scratch+(*scratch+1))-spot);
|
|
PeteAppendText(name+1,*name,APTE);
|
|
ComposeRString(name,URL_FMT,ProtocolStrn+proPh2,server);
|
|
PCatC(name,'\015');
|
|
PeteAppendText(name+1,*name,APTE);
|
|
PeteSetURLRescan(APTE,0);
|
|
*name = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PCatC(scratch,'\015');
|
|
PeteAppendText(scratch+1,*scratch,APTE);
|
|
}
|
|
if (code>=200) break;
|
|
}
|
|
PeteCalcOn(APTE);
|
|
PhFocus(QPTE);
|
|
}
|
|
|
|
/************************************************************************
|
|
* ContactQi - make contact with the QI server
|
|
************************************************************************/
|
|
short ContactQi(TransStream stream)
|
|
{
|
|
Str255 serverName;
|
|
short err;
|
|
long phPort;
|
|
|
|
if (Live) return(noErr);
|
|
|
|
if (!GetPhServerGlobals(nil, &phPort))
|
|
return paramErr;
|
|
|
|
MakeFallbackName(serverName,Fallback);
|
|
err=ConnectTrans(stream,serverName,phPort,!UseCTB,GetRLong(OPEN_TIMEOUT));
|
|
while (!UseCTB&&((err==openFailed)||(err==errLostConnection)))
|
|
{
|
|
DestroyTrans(stream);
|
|
if (isdigit(serverName[1])) {Fallback++;break;} /* don't fallback on ip addresses. */
|
|
IncrementPhServer(serverName);
|
|
err=ConnectTrans(stream,serverName,phPort,True,GetRLong(OPEN_TIMEOUT));
|
|
}
|
|
if (err&&Fallback)
|
|
{
|
|
Fallback = 0;
|
|
SilenceTrans(stream,False);
|
|
NotePhServer(GetRString(serverName,NOONE));
|
|
}
|
|
else if (Fallback)
|
|
NotePhServer(serverName);
|
|
if (!err && UseCTB) Pause(120L);
|
|
|
|
if (!err && PrefIsSet(PREF_PH_LIVE)) Live = True;
|
|
else Live = False;
|
|
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* NotePhServer - tell the user who we're talking to.
|
|
************************************************************************/
|
|
void NotePhServer(UPtr serverName)
|
|
{
|
|
Str255 msg;
|
|
ComposeRString(msg,PH_SUCCEED,serverName);
|
|
PeteAppendText(msg+1,*msg,APTE);
|
|
}
|
|
|
|
/************************************************************************
|
|
* IncrementPhServer - go on to the next ph server
|
|
************************************************************************/
|
|
void IncrementPhServer(UPtr serverName)
|
|
{
|
|
Str255 fmt,msg,newServer;
|
|
|
|
Fallback++;
|
|
MakeFallbackName(newServer,Fallback);
|
|
GetRString(fmt,PH_FAIL);
|
|
utl_PlugParams(fmt,msg,serverName,newServer,nil,nil);
|
|
PeteAppendText(msg+1,*msg,APTE);
|
|
PCopy(serverName,newServer);
|
|
}
|
|
|
|
/************************************************************************
|
|
* MakeFallbackName - add the appropriate numeral to a hostname
|
|
************************************************************************/
|
|
void MakeFallbackName(UPtr serverName, short fallback)
|
|
{
|
|
char *spot;
|
|
Str15 num;
|
|
|
|
if (!GetPhServerGlobals(serverName, nil))
|
|
{
|
|
serverName[0] = 0;
|
|
return;
|
|
}
|
|
|
|
if (fallback)
|
|
{
|
|
NumToString(fallback,num);
|
|
spot = strchr(serverName+1,'.');
|
|
if (!spot) spot=serverName+*serverName+1;
|
|
BMD(spot,spot+*num,*serverName-(spot-serverName)+2);
|
|
BMD(num+1,spot,*num);
|
|
*serverName += *num;
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* GetFingerServerName - return the name of the finger server
|
|
**********************************************************************/
|
|
PStr GetFingerServerName(PStr serverName)
|
|
{
|
|
GetPref(serverName,PREF_FINGER_HOST);
|
|
if (!*serverName) GetSMTPInfo(serverName);
|
|
return serverName;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* GetDirSvcServerName - return the name of the server for Ph or LDAP
|
|
**********************************************************************/
|
|
PStr GetDirSvcServerName(PStr serverName)
|
|
{
|
|
GetPref(serverName, PREF_PH);
|
|
if (!*serverName)
|
|
GetRString(serverName, PH_HOST);
|
|
return(serverName);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* SendQiCommand - send the current command to qi
|
|
************************************************************************/
|
|
short SendQiCommand(TransStream stream,UPtr cmd)
|
|
{
|
|
Str15 newline;
|
|
|
|
if (!*GetRString(newline,PH_NEWLINE)) PCopy(newline,NewLine);
|
|
|
|
return(SendTrans(stream,cmd+1,*cmd,newline+1,*newline,nil));
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetQiResponse - read a response from the nameserver
|
|
************************************************************************/
|
|
short GetQiResponse(TransStream stream,PStr cmd)
|
|
{
|
|
Str63 separator;
|
|
Str255 buffer;
|
|
long size;
|
|
short ordinal = 0;
|
|
short lastOrdinal = 0;
|
|
short response=600;
|
|
Boolean tooBig = False;
|
|
Str63 mailfield, maildomain, mailbox;
|
|
Str63 rem1, rem2, rem1Content, rem2Content, key;
|
|
UserEntryHandle ueh;
|
|
long start;
|
|
Str255 name, fContent;
|
|
UPtr spot;
|
|
short nFields = CountStrn(PhNickPhStrn);
|
|
UHandle **fields = nil;
|
|
short fIndex;
|
|
NicknameTagMapRec tagMap;
|
|
Boolean haveTagMap;
|
|
Str255 serviceName;
|
|
|
|
/*
|
|
* figure out what we need to remember, if anything
|
|
*/
|
|
if (SiteInfo)
|
|
{
|
|
*mailfield = *mailbox = *maildomain = *rem1 = *rem2 = 0;
|
|
AAFetchResData(SiteInfo,PhStrn+phfMaildomain,maildomain);
|
|
AAFetchResData(SiteInfo,PhStrn+phfMailfield,mailfield);
|
|
AAFetchResData(SiteInfo,PhStrn+phfMailbox,mailbox);
|
|
|
|
if (*maildomain)
|
|
{
|
|
if (*mailfield) PCopy(rem1,mailfield);
|
|
else GetRString(rem1,PhStrn+phfAlias);
|
|
if (*mailbox) PCopy(rem2,mailbox);
|
|
else GetRString(rem2,PhStrn+phfEmail);
|
|
}
|
|
else if (*mailfield)
|
|
PCopy(rem1,mailfield);
|
|
else if (*mailbox)
|
|
PCopy(rem1,mailbox);
|
|
else
|
|
GetRString(rem1,PhStrn+phfEmail);
|
|
}
|
|
|
|
/*
|
|
* do it
|
|
*/
|
|
if (haveTagMap = GetNicknameTagMap (GetRString (serviceName, ProtocolStrn + proPh), DirSvcServer, &tagMap) ? false : true)
|
|
nFields = tagMap.count;
|
|
|
|
fields = NuHTempOK(nFields*sizeof(UHandle));
|
|
WriteZero(LDRef(fields),nFields*sizeof(UHandle));
|
|
UL(fields);
|
|
|
|
PeteCalcOff(APTE);
|
|
|
|
GetRString(separator,PH_SEPARATOR);
|
|
do
|
|
{
|
|
size=sizeof(buffer);
|
|
response = QiLine(stream,&ordinal,buffer,&size);
|
|
if (tooBig) continue;
|
|
if (response==598)
|
|
{
|
|
Str255 query;
|
|
GetRString(query,PH_QUERY);
|
|
PCopy(buffer,cmd);
|
|
PSCat(query,buffer);
|
|
PCatC(query,' ');
|
|
PCatR(query,PH_RETURN);
|
|
//if (TransOut) TransLit(query+1,*query,TransOut);
|
|
response = 0;
|
|
if (SendTrans(stream,query+1,*query,Lf+1,1,nil)) response = 600;
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* new entry. handle separator and address extraction
|
|
*/
|
|
if (ordinal != lastOrdinal)
|
|
{
|
|
if (!lastOrdinal) PhRememberServer();
|
|
if (lastOrdinal && *rem1 && *rem1Content && (!*rem2 || *rem2Content))
|
|
{
|
|
/* hey, we have to save it! */
|
|
ueh = NewZH(UserEntry);
|
|
if (ueh)
|
|
{
|
|
FormatPhEmail(rem1Content,rem2Content,name,ueh);
|
|
(*ueh)->start = start;
|
|
start = PETEGetTextLen(PETE,APTE);
|
|
(*ueh)->end = start;
|
|
LL_Queue(UserList,ueh,(UserEntryHandle));
|
|
(*ueh)->fields = fields;
|
|
fields = NuHTempOK(nFields*sizeof(UHandle));
|
|
WriteZero(LDRef(fields),nFields*sizeof(UHandle));
|
|
UL(fields);
|
|
PSCopy((*ueh)->name,name);
|
|
}
|
|
}
|
|
*name = *rem1Content = *rem2Content = 0; /* clear */
|
|
PeteAppendText(separator+1,*separator,APTE);
|
|
start = PETEGetTextLen(PETE,APTE);
|
|
lastOrdinal = ordinal;
|
|
}
|
|
|
|
if (response < 600)
|
|
(void) PeteAppendText(buffer,size,APTE);
|
|
|
|
if (-300<response && response<=-200 && (*rem1 || *rem2))
|
|
{
|
|
*buffer = size-1; /* make into pascal string and trim last char */
|
|
for (spot=buffer+1;spot<buffer+*buffer;spot++) if (*spot==' ') break;
|
|
for (spot++;spot<buffer+*buffer;spot++) if (*spot!=' ') break;
|
|
if (spot<buffer+*buffer)
|
|
{
|
|
if (PToken(buffer,key,&spot,":") && PToken(buffer,fContent,&spot,"\377"))
|
|
{
|
|
if (!*name && EqualStrRes(key,PhStrn+phfName))
|
|
PSCopy(name,fContent);
|
|
if (*rem1 && !*rem1Content && StringSame(key,rem1))
|
|
PSCopy(rem1Content,fContent);
|
|
if (*rem2 && !*rem2Content && StringSame(key,rem2))
|
|
PSCopy(rem2Content,fContent);
|
|
if (fields)
|
|
{
|
|
fIndex = haveTagMap ? FindServiceTagIndex (&tagMap, key) : FindSTRNIndex(PhNickPhStrn,key);
|
|
if (fIndex)
|
|
if (*fContent)
|
|
PhRememberField(fields,fIndex,fContent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while(response<200);
|
|
|
|
PeteCalcOn(APTE);
|
|
|
|
ZapFields(fields);
|
|
ZapHandle(fields);
|
|
if (haveTagMap)
|
|
DisposeNicknameTagMap (&tagMap);
|
|
return(response);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PhRememberField - remember an interesting ph field
|
|
**********************************************************************/
|
|
OSErr PhRememberField(UHandle **fields,short i,PStr data)
|
|
{
|
|
Handle temp;
|
|
|
|
/*
|
|
* 0-indexed, not 1-indexed
|
|
*/
|
|
i--;
|
|
|
|
/*
|
|
* fix up the data
|
|
*/
|
|
TrimWhite(data);
|
|
TrimInitialWhite(data);
|
|
|
|
/*
|
|
* create the handle?
|
|
*/
|
|
if (!(*fields)[i])
|
|
{
|
|
temp = NuHTempOK(0);
|
|
if (!temp) return(MemError());
|
|
(*fields)[i] = temp;
|
|
}
|
|
|
|
/*
|
|
* add an encoded newline
|
|
*/
|
|
if (GetHandleSize((*fields)[i]))
|
|
{
|
|
PtrAndHand("\003",(*fields)[i],1);
|
|
if (MemError()) return(MemError());
|
|
}
|
|
|
|
/*
|
|
* add the data
|
|
*/
|
|
PtrAndHand(data+1,(*fields)[i],*data);
|
|
return(MemError());
|
|
}
|
|
|
|
/**********************************************************************
|
|
* FormatPhEmail - format the email address for a ph entry
|
|
**********************************************************************/
|
|
void FormatPhEmail(PStr rem1, PStr rem2, PStr name, UserEntryHandle ueh)
|
|
{
|
|
Str255 address;
|
|
Str31 fmt;
|
|
Str63 maildomain;
|
|
Str255 mailbox;
|
|
|
|
TrimWhite(rem1); TrimInitialWhite(rem1);
|
|
TrimWhite(rem2); TrimInitialWhite(rem2);
|
|
TrimWhite(name); TrimInitialWhite(name);
|
|
GetRString(fmt,(*rem2 && !PIndex(rem1,'@'))?PH_ALIAS_FMT:PH_BOX_FMT);
|
|
if (AAFetchResData(SiteInfo,PhStrn+phfMaildomain,maildomain)) *maildomain = 0;
|
|
utl_PlugParams(fmt,mailbox,rem1,maildomain,rem2,nil);
|
|
CanonAddr(address,mailbox,name);
|
|
PCopy((*ueh)->address,address);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CloseQi - close the qi connection
|
|
************************************************************************/
|
|
void CloseQi(TransStream stream)
|
|
{
|
|
Str255 buffer;
|
|
long size;
|
|
Str63 quitCmd;
|
|
|
|
GetRString(quitCmd,PH_QUIT);
|
|
/*
|
|
* do it
|
|
*/
|
|
if (!CommandPeriod && !SendTrans(stream,quitCmd+1,*quitCmd,Lf+1,1,nil))
|
|
{
|
|
for (size=sizeof(buffer);
|
|
QiLine(stream,nil,buffer,&size)<200;
|
|
size=sizeof(buffer))
|
|
;
|
|
}
|
|
|
|
DisTrans(stream);
|
|
}
|
|
|
|
/************************************************************************
|
|
* QiLine - read a line from QI
|
|
************************************************************************/
|
|
int QiLine(TransStream stream,short *ordinal, UPtr text, long *size)
|
|
{
|
|
short result;
|
|
UPtr spot;
|
|
short ord;
|
|
|
|
if (RecvLine(stream,text,size)) return(600);
|
|
result = Atoi(text);
|
|
if (!result)
|
|
{
|
|
*size = 0;
|
|
return(100);
|
|
}
|
|
for (spot=text;*spot!=':';spot++);
|
|
ord = 0;
|
|
for (spot++;*spot>='0' && *spot <= '9';spot++)
|
|
ord = ord * 10 + *spot - '0';
|
|
if (ord)
|
|
{
|
|
*size -= spot-text+1;
|
|
BMD(spot+1,text,*size);
|
|
}
|
|
if (ordinal) *ordinal = ord;
|
|
if (TransIn) TransLit(text,*size,TransIn);
|
|
return(result);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhFocus - set the text area
|
|
************************************************************************/
|
|
void PhFocus(PETEHandle pte)
|
|
{
|
|
PeteFocus(Win,pte,True);
|
|
Win->ro = pte==APTE;
|
|
if (Win->ro) PhOutline(-1);
|
|
else PhOutline(PETEGetTextLen(PETE,QPTE)?CurDirSvcButton():-1);
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhFixFont - fix the font in the Ph window
|
|
************************************************************************/
|
|
void PhFixFont(void)
|
|
{
|
|
#ifdef BETA
|
|
BIG UGLY COMPILER ERROR
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************
|
|
* NewPhHost - install a new ph host
|
|
************************************************************************/
|
|
void NewPhHost(void)
|
|
{
|
|
if (PhGlobals)
|
|
{
|
|
PhKill();
|
|
ResetServerGlobals();
|
|
RedisplayPhHost();
|
|
PeteDelete(APTE,0,0x7fffffff);
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* RedisplayPhHost - display a new ph host
|
|
**********************************************************************/
|
|
void RedisplayPhHost(void)
|
|
{
|
|
Str255 newLabel;
|
|
StringPtr serverNamePtr;
|
|
Str255 serverNameStr;
|
|
Str255 serverTypeStr;
|
|
|
|
LockPhGlobals();
|
|
switch (GetTargetDirSvcType())
|
|
{
|
|
case phLookup:
|
|
serverNamePtr = DirSvcServer;
|
|
GetRString(serverTypeStr, PH_NAME);
|
|
break;
|
|
case fingerLookup:
|
|
serverNamePtr = FingerServer;
|
|
GetRString(serverTypeStr, FINGER);
|
|
break;
|
|
case ldapLookup:
|
|
serverNamePtr = DirSvcServer;
|
|
GetRString(serverTypeStr, LDAP_NAME);
|
|
break;
|
|
default:
|
|
serverNamePtr = DirSvcServer;
|
|
serverTypeStr[0] = 0;
|
|
break;
|
|
}
|
|
PCopy(serverNameStr, serverNamePtr);
|
|
FixURLString(serverNameStr);
|
|
if (serverTypeStr[0])
|
|
ComposeRString(newLabel, PH_LABEL, serverTypeStr, serverNameStr);
|
|
else
|
|
ComposeRString(newLabel, PH_LABEL_NO_TYPE, serverNameStr);
|
|
UnlockPhGlobals();
|
|
PCopy(Label,newLabel);
|
|
InvalPhWindowTop();
|
|
UpdateMyWindow(GetMyWindowWindowPtr(Win));
|
|
Fallback = 0;
|
|
PhKill();
|
|
}
|
|
|
|
/************************************************************************
|
|
* DoFinger - do the finger 'protocol'
|
|
************************************************************************/
|
|
void DoFinger(TransStream stream, UPtr cmd)
|
|
{
|
|
UPtr atSign = strchr(cmd+1,'@');
|
|
short uLen;
|
|
Str255 buffer;
|
|
long size;
|
|
Boolean gotSome=False;
|
|
|
|
if (atSign)
|
|
{
|
|
uLen = atSign-cmd-1;
|
|
MakePStr(buffer,atSign+1,*cmd - uLen - 1);
|
|
buffer[*buffer+1] = 0;
|
|
}
|
|
else
|
|
{
|
|
PCopy(buffer,FingerServer);
|
|
uLen = *cmd;
|
|
}
|
|
|
|
if (!ConnectTrans(stream,buffer,GetRLong(FINGER_PORT),False,GetRLong(OPEN_TIMEOUT)))
|
|
{
|
|
if (!SendTrans(stream,uLen?cmd+1:" ",uLen?uLen:1,CrLf+1,2,nil))
|
|
{
|
|
SilenceTrans(stream,True);
|
|
for (size=sizeof(buffer)-2;!NetRecvLine(stream,buffer,&size);size=sizeof(buffer)-2)
|
|
{
|
|
if (TransIn) TransLit(buffer,size,TransIn);
|
|
PeteAppendText(buffer,size,APTE); SFWTC = True;
|
|
}
|
|
}
|
|
DisTrans(stream);
|
|
}
|
|
}
|
|
|
|
#pragma segment Transport
|
|
/************************************************************************
|
|
* RecvLine - get some text from the remote host.
|
|
************************************************************************/
|
|
OSErr NetRecvLine(TransStream stream, UPtr line,long *size)
|
|
{
|
|
long count;
|
|
UPtr anchor, end;
|
|
short err;
|
|
static int RcvBufferSize;
|
|
long bSize = *size;
|
|
Byte c;
|
|
|
|
if (!(stream->RcvBuffer) || !*(stream->RcvBuffer)) return(CommandPeriod ? userCancelled : memFullErr);
|
|
*size = 0;
|
|
if (!RcvBufferSize) RcvBufferSize = GetHandleSize_(stream->RcvBuffer);
|
|
|
|
anchor = line;
|
|
end = line+bSize-1;
|
|
while (anchor < end) /* need more chars */
|
|
if (stream->RcvSpot>=0) /* there are some buffered chars */
|
|
{
|
|
UPtr rPtr = *(stream->RcvBuffer)+stream->RcvSpot;
|
|
for(c=*rPtr++;anchor<end;c=*rPtr++)
|
|
if (c && c!='\015')
|
|
{
|
|
*anchor++ = c;
|
|
if (c=='\012')
|
|
{
|
|
anchor[-1] = '\015';
|
|
break;
|
|
}
|
|
}
|
|
if (c!='\012') rPtr--; /* whoops. back up. */
|
|
stream->RcvSpot = rPtr - *(stream->RcvBuffer);
|
|
if (stream->RcvSpot>stream->RcvSize) /* newline was sentinel */
|
|
anchor--;
|
|
if (stream->RcvSpot>=stream->RcvSize) /* we have emptied the buffer */
|
|
stream->RcvSpot = -1;
|
|
if (anchor>line && anchor[-1]=='\015' || anchor>=end) /* found a valid newline, or filled buffer */
|
|
{
|
|
*size = anchor-line;
|
|
*anchor = 0; /* terminate */
|
|
return(noErr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
count = RcvBufferSize-1;
|
|
if (err=RecvTrans(stream,LDRef(stream->RcvBuffer),&count)) /* get some chars */
|
|
count=0;
|
|
UL(stream->RcvBuffer);
|
|
if (count)
|
|
{
|
|
#ifdef TREAT_BODY_CR_AS_CRLF
|
|
// Turn bare CR into bare LF. Bare LF will be treated by
|
|
// the rest of the code as CRLF, and bare CR is illegal,
|
|
// though it is sometimes generated by -- you guessed it --
|
|
// Exchange, when CRLF is really meant.
|
|
//
|
|
// We do a sloppy job below, and actually will miss a lone
|
|
// CR that happens to land on a buffer boundary, but ASK ME
|
|
// IF I CARE!!!!
|
|
{
|
|
UPtr cr = *stream->RcvBuffer;
|
|
UPtr end = cr+count-1;
|
|
for (;cr<end;cr++)
|
|
if (cr[0]=='\015' && cr[1]!='\012') cr[0] = '\012';
|
|
}
|
|
// End of disgusting Exchange workaround
|
|
#endif //TREAT_BODY_CR_AS_CRLF
|
|
|
|
(*(stream->RcvBuffer))[count] = '\012'; /* sentinel */
|
|
stream->RcvSize = count;
|
|
stream->RcvSpot = 0; }
|
|
if (err)
|
|
{
|
|
*size = anchor-line;
|
|
line[*size] = 0;
|
|
return(err);
|
|
}
|
|
}
|
|
*size = anchor - line;
|
|
if (*size) line[*size] = 0; /* null terminate */
|
|
return(err==userCancelled ? err : (*size ? noErr : err));
|
|
}
|
|
|
|
/**********************************************************************
|
|
*
|
|
**********************************************************************/
|
|
void PhKill(void)
|
|
{
|
|
if (PhGlobals && Live)
|
|
{
|
|
CloseQi(PhStream);
|
|
DestroyTrans(PhStream);
|
|
#ifdef CTB
|
|
if (UseCTB) HangUpThePhone();
|
|
#endif
|
|
Live = False;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhRememberServer - remember the current ph server
|
|
************************************************************************/
|
|
void PhRememberServer(void)
|
|
{
|
|
Str255 url, server;
|
|
short which;
|
|
short n;
|
|
|
|
if (DirSvcType==phLookup)
|
|
PhMakeURL(url);
|
|
else if (DirSvcType==ldapLookup)
|
|
LDAPMakeURL(url);
|
|
else
|
|
return; // unknown type!
|
|
|
|
which = FindSTRNIndex(RecentDirServStrn,url);
|
|
|
|
if (which==1) return; // already at the top of the list
|
|
|
|
// move all the rest down
|
|
n = which ? which-1 : CountStrn(RecentDirServStrn);
|
|
for (;n;n--)
|
|
ChangeStrn(RecentDirServStrn,n+1,GetRString(server,RecentDirServStrn+n));
|
|
// put it at the top of the list
|
|
ChangeStrn(RecentDirServStrn,1,url);
|
|
|
|
// make sure we don't remember more servers than we're supposed to
|
|
ChangeStrn(RecentDirServStrn,GetRLong(RECENT_DIR_LIMIT)+1,"");
|
|
}
|
|
|
|
/************************************************************************
|
|
* PhMakeURL - make a ph URL out of the current server stuff
|
|
************************************************************************/
|
|
PStr PhMakeURL(PStr url)
|
|
{
|
|
Str31 portStr;
|
|
|
|
GetRString(url,ProtocolStrn+proPh);
|
|
PCat(url,"\p://");
|
|
PCat(url,DirSvcServer);
|
|
if (DirSvcPort && DirSvcPort!=GetRLong(PH_PORT))
|
|
{
|
|
PCatC(url,':');
|
|
NumToString((uLong)DirSvcPort,portStr);
|
|
PCat(url,portStr);
|
|
}
|
|
PCatC(url,'/');
|
|
return(url);
|
|
}
|
|
|
|
/************************************************************************
|
|
* LDAPMakeURL - make an LDAP URL out of the current server stuff
|
|
************************************************************************/
|
|
PStr LDAPMakeURL(PStr url)
|
|
{
|
|
Str255 s;
|
|
short a;
|
|
UPtr attr;
|
|
|
|
// ldap://
|
|
GetRString(url,ProtocolStrn+proLDAP);
|
|
PCat(url,"\p://");
|
|
|
|
// server
|
|
PCat(url,DirSvcServer);
|
|
// port
|
|
if (DirSvcPort && DirSvcPort!=GetRLong(LDAP_PORT_REALLY))
|
|
{
|
|
PCatC(url,':');
|
|
NumToString((uLong)DirSvcPort,s);
|
|
PCat(url,s);
|
|
}
|
|
PCatC(url,'/');
|
|
|
|
// is there a base object?
|
|
PCat(url,LDAPBaseObject);
|
|
|
|
// do we have fields?
|
|
if (LDAPAttrList)
|
|
{
|
|
PCatC(url,'?');
|
|
for (a=0;a<(*LDAPAttrList)->numLogicalAttrs;a++)
|
|
{
|
|
attr = ((char**)(*(*LDAPAttrList)->attrList))[a];
|
|
CtoPCpy(s,attr);
|
|
if (a) PCatC(url,',');
|
|
PCat(url,s);
|
|
}
|
|
}
|
|
|
|
return(url);
|
|
}
|
|
|
|
|
|
#pragma segment Balloon
|
|
PhWinItemIndex CalcPhHelpItem(MyWindowPtr win, Point mouseLoc, Rect *itemRect)
|
|
|
|
{
|
|
#pragma unused (win)
|
|
|
|
|
|
if (PtInControl(mouseLoc, OkButton))
|
|
{
|
|
GetControlBounds(OkButton,itemRect);
|
|
return phWinLookupBtnItem;
|
|
}
|
|
if (PtInControl(mouseLoc, FingerButton))
|
|
{
|
|
GetControlBounds(FingerButton,itemRect);
|
|
return phWinFingerBtnItem;
|
|
}
|
|
if (PtInControl(mouseLoc, ListButton))
|
|
{
|
|
GetControlBounds(ListButton,itemRect);
|
|
return phWinGlobeBtnItem;
|
|
}
|
|
if (PtInControl(mouseLoc, ToButton))
|
|
{
|
|
GetControlBounds(ToButton,itemRect);
|
|
return phWinToBtnItem;
|
|
}
|
|
if (PtInControl(mouseLoc, CcButton))
|
|
{
|
|
GetControlBounds(CcButton,itemRect);
|
|
return phWinCcBtnItem;
|
|
}
|
|
if (PtInControl(mouseLoc, BccButton))
|
|
{
|
|
GetControlBounds(BccButton,itemRect);
|
|
return phWinBccBtnItem;
|
|
}
|
|
if (PtInRect(mouseLoc, &QRect))
|
|
{
|
|
*itemRect = QRect;
|
|
return phWinQueryTextItem;
|
|
}
|
|
if (PtInRect(mouseLoc, &ARect))
|
|
{
|
|
*itemRect = ARect;
|
|
return phWinResponseTextItem;
|
|
}
|
|
|
|
itemRect->top = itemRect->left = itemRect->bottom = itemRect->right = 0;
|
|
return 0;
|
|
}
|
|
|
|
|
|
#pragma segment Balloon
|
|
/************************************************************************
|
|
* PhHelp - do balloon help for the ph window
|
|
************************************************************************/
|
|
void PhHelp(MyWindowPtr win,Point mouse)
|
|
{
|
|
Rect r;
|
|
short hnum;
|
|
short itemIndex;
|
|
DirSvcLookupType defaultLookupType;
|
|
|
|
itemIndex = CalcPhHelpItem(win, mouse, &r);
|
|
if (!itemIndex)
|
|
{
|
|
hnum = 100; /* index value that's off the scale, to indicate it's not a UI item */
|
|
MyBalloon(&r,100,0,PHWIN_HELP_STRN+hnum,0,nil);
|
|
return;
|
|
}
|
|
|
|
defaultLookupType = GetTargetDirSvcType();
|
|
switch (defaultLookupType)
|
|
{
|
|
case phLookup:
|
|
case fingerLookup:
|
|
case ldapLookup:
|
|
case genericLookup:
|
|
break;
|
|
default:
|
|
hnum = 100; /* index value that's off the scale, to indicate it's not a UI item */
|
|
MyBalloon(&r,100,0,PHWIN_HELP_STRN+hnum,0,nil);
|
|
return;
|
|
}
|
|
|
|
switch (itemIndex)
|
|
{
|
|
case phWinLookupBtnItem:
|
|
switch (defaultLookupType)
|
|
{
|
|
case phLookup:
|
|
hnum = CanQuery() ? 1 : 4;
|
|
break;
|
|
case ldapLookup:
|
|
hnum = CanQuery() ? 2 : 5;
|
|
break;
|
|
case genericLookup:
|
|
hnum = CanQuery() ? 3 : 6;
|
|
break;
|
|
default:
|
|
hnum = 100; /* index value that's off the scale, to indicate it's not a UI item */
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case phWinFingerBtnItem:
|
|
if (UseCTB)
|
|
hnum = 9;
|
|
else if (CanQuery())
|
|
hnum = 7;
|
|
else
|
|
hnum = 8;
|
|
break;
|
|
|
|
case phWinGlobeBtnItem:
|
|
hnum = 10;
|
|
break;
|
|
|
|
case phWinToBtnItem:
|
|
if (defaultLookupType == fingerLookup)
|
|
hnum = 13;
|
|
else if (CanAddress())
|
|
hnum = 11;
|
|
else
|
|
hnum = 12;
|
|
break;
|
|
|
|
case phWinCcBtnItem:
|
|
if (defaultLookupType == fingerLookup)
|
|
hnum = 16;
|
|
else if (CanAddress())
|
|
hnum = 14;
|
|
else
|
|
hnum = 15;
|
|
break;
|
|
|
|
case phWinBccBtnItem:
|
|
if (defaultLookupType == fingerLookup)
|
|
hnum = 19;
|
|
else if (CanAddress())
|
|
hnum = 17;
|
|
else
|
|
hnum = 18;
|
|
break;
|
|
|
|
case phWinQueryTextItem:
|
|
hnum = 19 + defaultLookupType;
|
|
break;
|
|
|
|
case phWinResponseTextItem:
|
|
hnum = 23 + defaultLookupType;
|
|
break;
|
|
|
|
default:
|
|
hnum = 100; /* index value that's off the scale, to indicate it's not a UI item */
|
|
}
|
|
|
|
MyBalloon(&r,100,0,PHWIN_HELP_STRN+hnum,0,nil);
|
|
}
|
|
|
|
/**********************************************************************
|
|
*
|
|
**********************************************************************/
|
|
OSErr PhListConnectError(short error)
|
|
{
|
|
OSErr err = noErr;
|
|
Str255 errorString, e;
|
|
|
|
if (error != userCancelled)
|
|
{
|
|
Zero(e);
|
|
OTErrorToString(error, e);
|
|
|
|
ComposeRString(errorString,PH_CONNECT_ERROR,error,e);
|
|
if (PeteLen(APTE)) PeteAppendText(Cr+1,*Cr,APTE);
|
|
PeteAppendText(errorString+1,*errorString,APTE);
|
|
}
|
|
return (err);
|
|
} |