/*$Copyright:
 * Copyright (C) 1992.5.22. Recruit Co.,Ltd. 
 * Institute for Supercomputing Research
 * All rights reserved.
 * NewsBase  by ISR, Kazuto MIYAI, Gary ARAKAKI, Katsunori SUZUKI, Kok-meng Lue
 *
 * You may freely copy, distribute and reuse the code in this program under 
 * following conditions.
 * - to include this notice in the source code, if it is to be distributed 
 *   with source code.
 * - to add the file named "COPYING" within the code, which shall include 
 *   GNU GENERAL PUBLIC LICENSE(*).
 * - to display an acknowledgement in binary code as follows: "This product
 *   includes software developed by Recruit Co.,Ltd., ISR."
 * - to display a notice which shall state that the users may freely copy,
 *   distribute and reuse the code in this program under GNU GENERAL PUBLIC
 *   LICENSE(*)
 * - to indicate the way to access the copy of GNU GENERAL PUBLIC LICENSE(*)
 *
 *   (*)GNU GENERAL PUBLIC LICENSE is stored in the file named COPYING
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
$*/
/*
 *    INNTP
 */


#import "INNTP.h"

#import <string.h>
#import <stdlib.h>
#import <sys/file.h>
#import <sys/uio.h>
#import <sys/types.h>
#import <sys/socket.h>
#import <streams/streams.h>
#import <netdb.h>
#import <netinet/in.h>

#import "response_codes.h"

#import <appkit/Panel.h>
#import <objc/Storage.h>

#import "Localization.h"

#define LoStr(key)      doLocalString(NULL,key,NULL)


@implementation INNTP

- init
{
    [super init];
    iNntpHostName = NULL;

    iResBufStorage = [[Storage alloc] initCount:0
				   elementSize:(unsigned)LINE_BUFFER_SIZE
				   description:(const char *)"@"];
    
    return self;
}


- (int)issueCommand:(const char *)command
{
    int         statusCode;

    if( !(inntpFile) ) {
        printf(" NNTP connection is not opened yet\n" );
        return 0;
    }

    fprintf( inntpFile, "%s\r\n", command );
    fflush( inntpFile );
    fseek( inntpFile, (long)0, SEEK_END );

    statusCode = [self _getResponse];

    return statusCode;
}

- (int)_getResponse
{
    int         statusCode;
   
    fscanf (inntpFile, "%[^\r]\r", iresponse);
    fgetc (inntpFile);                                          /* get \n */
                        /* read response code from textual response line */
    sscanf (iresponse, "%d", &statusCode);
   
    return statusCode;
}

- openServer:(const char *)serverName
{
    struct servent	*nntpEnt;
    struct protoent	*nntpProtoEnt;
    struct hostent	*nntpHost;
    struct sockaddr_in	nntpServer;
    int 		inCode;
    char 		inCodeText[512];
    BOOL		canPost;

    // store nntp hostname for reconnecting
    if (iNntpHostName == NULL) {
	iNntpHostName = NXCopyStringBuffer(serverName);
    }
    
    if ((nntpEnt = getservbyname("nntp", "tcp")) == NULL) {
	NXRunAlertPanel(LoStr("News Flash"),LoStr("Cannot find nntp service in 'services' database."),NULL,NULL,NULL);
      return nil;
    }

    if ((nntpProtoEnt = getprotobyname(nntpEnt->s_proto)) == NULL) {
	NXRunAlertPanel(LoStr("News Flash"),LoStr("Cannot lookup protocol type."),NULL,NULL,NULL);
	return nil;
    }

    if ((nntpSocket = socket(AF_INET, SOCK_STREAM, 
                             nntpProtoEnt->p_proto))== -1) {
	NXRunAlertPanel(LoStr("News Flash"),LoStr("Cannot create socket to news server."),NULL,NULL,NULL);
	return nil;
    }

    if ((nntpHost = gethostbyname((char *)serverName)) == NULL) {
	NXRunAlertPanel(LoStr("News Flash"),LoStr("Cannot find address of host %s."),NULL,NULL,NULL, serverName);
    return nil;
    }

  nntpServer.sin_family = nntpHost->h_addrtype;
  bcopy(nntpHost->h_addr, &nntpServer.sin_addr, nntpHost->h_length);
  nntpServer.sin_port = nntpEnt->s_port;
  if ((connect(nntpSocket, (struct sockaddr *) &nntpServer,
	sizeof(nntpServer))) == -1) {
    NXRunAlertPanel(LoStr("News Flash"),LoStr("Cannot connect to news server on %s."),NULL,NULL,NULL, serverName);
    return nil;
  }

  inntpFile = fdopen(nntpSocket, "r+");

  fscanf(inntpFile, "%d %[^\r]\r", &inCode, &inCodeText);
  fgetc(inntpFile);
  fseek(inntpFile, (long)0, SEEK_END);

  switch (inCode) {
    case OK_CANPOST:
    case OK_NOPOST:
      canPost = (inCode == OK_CANPOST);
      break;
    default:
      NXRunAlertPanel(LoStr("News Flash"),LoStr("News server on %s responded incorrectly."),NULL,NULL,NULL, serverName);
      return nil;
      break;
  }

  return self;
}

- reconnectServer
{
    fclose (inntpFile);

    if (iNntpHostName == NULL) {
	return nil;
    }
    return ([self openServer:iNntpHostName]);
}

- (char *)lastResponse
{
    return iresponse;
}

- free
{
    free(iNntpHostName);
    return ([super free]);
}

@end
