home *** CD-ROM | disk | FTP | other *** search
- //
- // Finger Version 1.0, a Windows Sockets Finger Client
- //
- // Copyright (C) 1994 by Zoran Dukic.
- //
- // Permission to use, modify, and distribute this software and its
- // documentation for any purpose and without fee is hereby granted, provided
- // that the above copyright notice appears in all copies and that both
- // that copyright notice and this permission notice appear in supporting
- // documentation. Zoran Dukic makes no claims as to the suitability of this
- // software for any purpose.
- //
- // Module NETWRKM uses Windows Sockets asynchronous (message based) calls to
- // query a remote finger server for a list of currently logged in users.
- // Module FINGER initiates the operation by calling FingerStart(), and
- // NETWRKM signals completion by calling FingerFinish().
- //
-
- /*****************************************************************************
- Module NETWRKM is reconstruction of the same module from the Finger 3.1,
- for C++, so here is the copyright notice for the Finger 3.1.
-
- Finger Version 3.1, a Windows Sockets Finger Client
-
- Copyright 1992, 1993 Network Research Corporation
-
- Permission to use, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted, provided
- that the above copyright notice appears in all copies and that both
- that copyright notice and this permission notice appear in supporting
- documentation. NRC makes no claims as to the suitability of this software
- for any purpose.
-
- 04/01/92 Lee Murach Created.
- 11/30/92 Lee Murach Adapted for WS 1.1 WSAAsyncSelect()
- 12/02/92 Lee Murach Restructured for Finger 3.0 integrated release
- 01/15/92 Lee Murach Change FD_READ to FD_READ | FD_CLOSE
- 03/01/93 Lee Murach Added WSAEWOULDBLOCK check to DoConnect()
- 03/25/93 Lee Murach Added per-user finger support.
- ******************************************************************************/
-
-
- #include "finger.h"
-
- extern char szAppName[]; // application's name
-
-
- TNetWnd::TNetWnd(PTWindowsObject AParent)
- :TWindow(AParent, "")
- {
- Attr.Style = WS_OVERLAPPEDWINDOW;
- Attr.X = CW_USEDEFAULT;
- Attr.Y = CW_USEDEFAULT;
- Attr.W = CW_USEDEFAULT;
- Attr.H = CW_USEDEFAULT;
-
- pReceiveList = NULL;
-
- int err;
-
- if ((err = WSAStartup(WSVERSION, &WSAData)) != 0) // register task with
- { // winsock tcp/ip API
- ((PTFingerWnd)Parent)->ReportWSError(err);
- DestroyWindow(Parent->HWindow); // kill application window &
- } // signal app exit
- }
-
-
- TNetWnd::~TNetWnd()
- {
- if(pReceiveList != NULL)delete pReceiveList;
- WSACleanup(); // disconnect from winsock
- };
-
-
-
- LPSTR TNetWnd::GetClassName()
- {
- return NETWINDOW;
- }
-
-
-
- void TNetWnd::GetWindowClass(WNDCLASS& wndclass)
- {
- TWindow::GetWindowClass(wndclass);
-
- wndclass.style = 0;
- wndclass.hIcon = 0;
- wndclass.hCursor = 0;
- wndclass.hbrBackground = 0;
- }
-
-
- //
- // FingerStart -- called by FINGER module to initiate a conversation with
- // the remote finger server. We start by resolving the finger tcp service
- // to a port number. Windows Sockets WSAAsync routines signal completion
- // by posting messages, which are dispatched to appropriate handlers.
- //
- void TNetWnd::FingerStart()
- {
- if (WSAAsyncGetServByName(HWindow, WM_SERVICE, "finger", "tcp",
- EntBuf, sizeof(EntBuf)) == NULL)
- {
- ReportFingerErr(FE_NOPORT);
- FingerFinish(FE_ERROR);
- }
- }
-
-
- // FingerFinish -- invoked when the finger operation is complete,
- // this function updates the display list & repaints the frame window
- // client area if the operation was successful.
- //
- void TNetWnd::FingerFinish(UINT Err)
- {
- ((PTFingerWnd)Parent)->FingerFinish(Err);
- }
-
-
- // ReportFingerErr -- prompt user with a finger specific error
- //
- void TNetWnd::ReportFingerErr(UINT Err)
- {
- ((PTFingerWnd)Parent)->ReportFingerErr(Err);
- };
-
-
-
- //
- // LoadEntBuf -- loads the EntBuf (sufficiently) with a HOSTENT and
- // referenced IPA. This is so we can return IPAs in the same
- // manner as a WSAAsync call.
- //
- void TNetWnd::LoadEntBuf(IPA ipa)
- {
- LPHOSTENT phe = (LPHOSTENT) EntBuf;
- LPPIPA ppipa = (LPPIPA) (EntBuf + sizeof(HOSTENT));
- LPIPA pipa = (LPIPA) (EntBuf + sizeof(HOSTENT) + sizeof(LPPIPA));
-
- _fmemset(phe, 0, sizeof(HOSTENT));
- phe->h_addr_list = (char FAR * FAR *) ppipa;
- *ppipa = pipa;
- *pipa = ipa;
- }
-
-
- //
- // DoResolveHost -- resolves host specifier to an IP address. Since we
- // allow a "dotted decimal" IP address to be entered in lieu of a DNS host
- // name, we check for this syntax before assuming a DNS name.
- //
- void TNetWnd::DoResolveHost(RTMessage Msg)
- {
- IPA ipa;
-
- if (WSAGETSELECTERROR(Msg.LParam))
- {
- ReportFingerErr(FE_NOPORT); // cannot locate finger service
- FingerFinish(FE_ERROR);
- return;
- }
-
- Port = ((SERVENT *)EntBuf)->s_port; // we're going to reuse the buffer
-
- // if host specifier is dotted decimal ip address, resolve right here
- if ((ipa = INET_ADDR(szHostName)) != INADDR_NONE)
- {
- LoadEntBuf(ipa);
- PostMessage(HWindow, WM_HOSTRESOLVED, 0, 0);
- return;
- }
-
- // assume specifier is DNS host name
- if (WSAAsyncGetHostByName(HWindow, WM_HOSTRESOLVED, szHostName,
- EntBuf, sizeof(EntBuf)) == NULL)
- {
- ReportFingerErr(FE_NOHOST);
- FingerFinish(FE_ERROR);
- }
-
- return;
- }
-
-
- //
- // DoConnect -- allocates a socket and connects to remote finger server.
- //
- void TNetWnd::DoConnect(RTMessage Msg)
- {
- if (WSAGETSELECTERROR(Msg.LParam))
- {
- ReportFingerErr(FE_NOHOST); // could not resolve host name
- FingerFinish(FE_ERROR);
- return;
- }
-
- if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) < WSABASEERR)
- {
- SOCKADDR_IN server;
- u_long block = FALSE;
- HOSTENT *phe = (HOSTENT *) EntBuf;
-
- memset(&server, 0, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_port = Port;
- server.sin_addr = *((IN_ADDR FAR *) *phe->h_addr_list);
-
- // post message when connect is established
- WSAAsyncSelect(Sock, HWindow, WM_CONNECTED, FD_CONNECT);
-
- if ( connect(Sock, (SOCKADDR *)&server, sizeof(server)) < 0 &&
- WSAGetLastError() != WSAEWOULDBLOCK)
- {
- ReportFingerErr(FE_NOCONN);
- FingerFinish(FE_ERROR);
- }
- }
- else
- {
- ReportFingerErr(FE_NOSOCK);
- FingerFinish(FE_ERROR);
- }
-
- return;
- }
-
-
- //
- // DoQuery -- sends a query for all currently logged in users to remote
- // server.
- //
-
- void TNetWnd::DoQuery(RTMessage Msg)
- {
- char msg[MAXUSER+3];
- int msglen;
-
- if (WSAGETSELECTERROR(Msg.LParam))
- {
- ReportFingerErr(FE_NOCONN); // could not connect to server
- FingerFinish(FE_ERROR);
- return;
- }
-
- // post message when data is available for read
- WSAAsyncSelect(Sock, HWindow, WM_OKTORECV, FD_READ | FD_CLOSE);
-
- strcpy(msg, szUser);
- strcat(msg, "\r\n");
- msglen = strlen(msg);
-
- if (send(Sock, msg, msglen, 0) != msglen)
- {
- ReportFingerErr(FE_NOSEND);
- FingerFinish(FE_ERROR);
- return;
- }
-
- LineLen = 0;
- maxLineLen = 0;
- pReceiveList = new Array(50,0,50); // new receive list will contain received data
-
- return;
- }
-
-
- //
- // DoRetrieval -- fetches ascii text from remote finger server, and builds
- // display list until the end of the text stream.
- //
- void TNetWnd::DoRetrieval(RTMessage)
- {
- static char buf[500];
- int nchars, err = 0;
-
- /* receives data not to exceed buf size & reenables notification
- of more data pending */
-
- if ((nchars = recv(Sock, (char FAR *)&buf, sizeof(buf), 0)) > 0)
- {
- PushChars(buf, nchars); // adds character to display list
- return;
- }
-
- closesocket(Sock); // don't need socket anymore
-
- if (nchars < 0)
- {
- delete pReceiveList;
- ReportFingerErr(FE_NORECV); // error during receive
- err = FE_ERROR;
- }
-
- FingerFinish(err); // signal end-of-finger
-
- return;
- }
-
-
-
- //
- // PushChars -- pushes buffer of characters into the display list;
- // expands tabs.
- //
- void TNetWnd::PushChars(char *buf, int buflen)
- {
- while (buflen--)
- {
- if (*buf == '\t')
- PushChars(TABSTRING, strlen(TABSTRING));
- else
- PushChar(*buf);
-
- buf++;
- }
- }
-
-
- //
- // PushChar -- pushes a character into the LineBuf. Pushes line into
- // the line list if <cr> encountered, or LineBuf is full. Discards
- // linefeeds.
- //
- void TNetWnd::PushChar(char ch)
- {
- if (LineLen < sizeof(LineBuf))
- if (ch != LF)
- if (ch != CR)
- LineBuf[LineLen++] = ch;
- else ; // discard carriage returns
- else
- {
- LineBuf[LineLen++] = ' ';
- PushLine(); // linefeeds signal newline
- }
- else
- PushLine();
- }
-
- //
- // PushLine -- pushes a text line into the accumulating list of text lines.
- //
- void TNetWnd::PushLine(VOID)
- {
- PTLine pLine = new TLine(LineBuf, LineLen);
-
- if(LineLen > maxLineLen) maxLineLen = LineLen;
- LineLen = 0;
-
- pReceiveList->add((Object&)*pLine);
- }
-
-
- //
- // Constructor for TLine object
- //
-
- TLine::TLine(char *srcbuf, int Len)
- {
- if ((sztext = (char *)malloc(Len)) != NULL)
- {
- strncpy(sztext, srcbuf, Len);
- LLen = Len;
- }
- };
-