/********** * Copyright (c) 2003-2004 Greg Parker. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``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 AUTHOR 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 "includes.h" #include "recordlist.h" #include "rsrc/rsrc.h" #include "formutils.h" #include "connectionlist.h" /* connection record format: 1 byte length n bytes hostname\0 1 byte length n bytes portname\0 (empty defaults to "22") 1 byte length n bytes username\0 */ #define ConnectionDBName "pssh Connection List" #define ConnectionDBType 'Conn' static DmOpenRef ConnectionDB = 0; static RecordList *ConnectionList = NULL; extern DmOpenRef OpenDB(UInt32 type, char *name, Boolean resDB, Boolean create); static Boolean ReadConnectionRecord(char *recordP, char **hostname, char **portname, char **username) CONNECTIONLIST_SEGMENT; static void DrawConnectionRecord(MemPtr recordP, UInt16 index, RectanglePtr bounds) CONNECTIONLIST_SEGMENT; Boolean ConnectionListInit(void) { ConnectionDB = OpenDB(ConnectionDBType, ConnectionDBName, false, true); if (!ConnectionDB) return false; ConnectionList = RecordListNew(ConnectionDB, MainFormID, MainConnectionTableID, MainConnectionScrollbarID, DrawConnectionRecord); if (!ConnectionList) return false; return true; } void ConnectionListFree(void) { if (ConnectionList) RecordListFree(ConnectionList); if (ConnectionDB) DmCloseDatabase(ConnectionDB); } void ConnectionListUpdate(void) { RecordListUpdate(ConnectionList); } UInt16 ConnectionListSelectedIndex(void) { return RecordListSelectedIndex(ConnectionList); } void ConnectionListSetSelectedIndex(UInt16 index) { RecordListSetSelectedIndex(ConnectionList, index); } void ConnectionListClearSelection(void) { RecordListClearSelection(ConnectionList); } void ConnectionListDeleteSelectedRecord(void) { RecordListDeleteSelectedRecord(ConnectionList); } Boolean ConnectionListHandleEvent(EventPtr event) { return RecordListHandleEvent(ConnectionList, event); } // returned values are only usable until recordP is unlocked static Boolean ReadConnectionRecord(char *recordP, char **hostname, char **portname, char **username) { #define CHECK_SPACE(n) do { if (p+(n)>end) goto bad; } while (0) Boolean ok = true; uint8_t *p = recordP; uint8_t *end = p + MemPtrSize(recordP); uint8_t len; // hostname field CHECK_SPACE(1); len = *p++; CHECK_SPACE(len); if (p[len-1] != '\0') goto bad; if (hostname) *hostname = p; p += len; // port number field CHECK_SPACE(1); len = *p++; CHECK_SPACE(len); if (p[len-1] != '\0') goto bad; if (portname) { if (len > 1) { *portname = p; } else { // no port specified - use default port *portname = "22"; } } p += len; // username field CHECK_SPACE(1); len = *p++; CHECK_SPACE(len); if (p[len-1] != '\0') goto bad; if (username) *username = p; p += len; return true; bad: return false; #undef CHECK_SPACE } MemHandle ConnectionListReadSelectedRecord(char **hostname, char **portname, char **username) { MemHandle recordH; MemPtr recordP; Boolean ok; recordH = RecordListQuerySelectedRecord(ConnectionList); if (!recordH) return false; recordP = MemHandleLock(recordH); ok = ReadConnectionRecord(recordP, hostname, portname, username); if (!ok) { MemHandleUnlock(recordH); return NULL; } else { return recordH; } } Boolean ConnectionListWriteSelectedRecord(FieldPtr hostFld, FieldPtr portFld, FieldPtr userFld) { Boolean ok = true; MemHandle recordH; UInt32 size; // resize record and write data to it size = (1+FldGetTextLength(hostFld)+1 + 1+FldGetTextLength(portFld)+1 + 1+FldGetTextLength(userFld)+1); recordH = RecordListGetSelectedRecord(ConnectionList, size); if (!recordH) { // error resizing or opening record // complain, leave existing record intact, don't connect // fixme ok = false; } else { Err err = 0; UInt32 written = 0; MemPtr recordP = MemHandleLock(recordH); if (!err) err = PrvStoreFieldToRecord(hostFld, recordP, &written); if (!err) err = PrvStoreFieldToRecord(portFld, recordP, &written); if (!err) err = PrvStoreFieldToRecord(userFld, recordP, &written); MemHandleUnlock(recordH); RecordListReleaseRecord(ConnectionList, recordH, true); if (err) { // error writing record // complain, delete record, don't connect // fixme ok = false; } } return ok; } static void DrawConnectionRecord(MemPtr recordP, UInt16 index, RectanglePtr bounds) { char *hostname; char *portname; char *username; if (ReadConnectionRecord(recordP, &hostname, &portname, &username)) { // "username@hostname" // "username@hostname:portname" (non-default port only) int x = bounds->topLeft.x + 1; int y = bounds->topLeft.y; int len; char *buf; int showPort; showPort = (0 != strcmp(portname, "") && 0 != strcmp(portname, "22")); len = strlen(username) + strlen("@") + strlen(hostname); if (showPort) { len += strlen(":") + strlen(portname); } buf = arena_malloc(len + 1); strcpy(buf, username); strcat(buf, "@"); strcat(buf, hostname); if (showPort) { strcat(buf, ":"); strcat(buf, portname); } WinDrawTruncChars(buf, len, x, y, bounds->topLeft.x + bounds->extent.x - x - 1); } }