/*  
==============================================================================
= MaxDiz V2.2 Is Free.  This Source Code Has Been Included To Show You That  =
= There Are No BackDoors Or Nasties Embedded In The Program.  If You Can     =
= Improve On The Code - COOL -.  Just Make Sure My Name Is In There With Your=
= Own When Ya Re-Release It.                                                 =
==============================================================================
*/
                                 
#define AddBits 1
#define DelBits 2
#define Normal  3 

void  CallHost( UBYTE c );
void  ShutDown( char *spawn );
void  ResetLogs( void );
int   COPY( char *From, char *To, int Action, char *Mode);
UBYTE ReadAccount( short id, struct UserData *user );
long  GetFileSize( char *Path );
void  SetDoing( char *what );
int   GetDiz( char *_EdBuff, char *_FilePath );
void  AddDiz( char *_EdBuff, char *_FilePath );
void  GetFileDate( struct DateStamp MyDateStamp );
void  Display( int Line, char *Item1, long Item2, char *Item3);
void  DisplayChart( int Num );
void  ReadItems( void );
void  SaveItems( void );
void  SetAdoptTemplates( void );
void  SaveDescription( void );
int   AskQuestions( void );
void  MakeCheckList( void );
void  CleanUpLongs( void );
int   Abort ( void );
int   CommentToAccount( struct UserData *MyData, char *Comment);
void  DisplayHelp( char *Item1, char *Item2 );
void  Pad_Text( int Num );


BPTR lock;

FILE *InFileA;
FILE *InFileB;
FILE *OtFileA; 
FILE *OtFileB;

char AccNo    [4 ];
char Suff     [4 ];
char Port     [4 ];

char OtTxt   [100];
char FmtStr  [100];

char _Free    [50];
char _Text    [50];
char _Short   [50];
char _EdBuff  [50];
char _Items3  [50];
char _DizPath [50];
char _Headers3[50];
char _Message3[50];
char _TempBuff[50];
char _FilePath[50];
char _DescPath[50];
char _LongDesc[50];
char _Comment [81];

char **bm;
char  *AdoptTitle = " Speed-Adopt";
char  *LastCommand;
char  *CheckList;

int  Display_Not = FALSE;
int  UseFile_ID  = FALSE;
int  UseDosDates = FALSE;
int  UseUploader = FALSE;

long DSize       = 0;
int  NumAdopted  = 0;
int  Desc_Not    = 0;
int  AccNum      = 0;
int  ItemID      = 0;
int  i           = 0;
int  c           = 0;


/***********************************
AreaTops Cnet Structures Declared.
***********************************/

struct  IsDate           AdoptionDate;
struct  stat             FileStats;
struct  Privs           *UserPrivs;
struct  FreeType         Free;
struct  TagItem         *TagList;
struct  WBArg           *fr_ArgList;
struct  MsgPort         *replyp;
struct  CPort           *cport;
struct  CMessage         cmess;
struct  HeaderType      *mh[999];
struct  MainPort        *MAINPORT;
struct  PortData        *PORTDATA;
struct  Library         *CNetBase = NULL;
struct  SignalSemaphore *SEM;
struct  NewSubboardType *Subboard;

/************************[ MAIN PROGRAM START ]***********************************/

int main( int argc, char **argv )

{
     if( argc<2 || !(cport = (struct CPort *)FindPort( argv[1] )) )
          {
          printf("\nMaxDiz v2.0 Beta File_Id Processor For Cnet V3.xx.\n");
          printf("A Cnet-C Pfile Usable Only From Cnet BBS Systems!\n");
          exit(0);
          }

     if( !(replyp = CreatePort( 0,0 )))
          exit(0);


     cmess.cn_Message.mn_ReplyPort   = replyp;
     cmess.cn_Message.mn_Length      = sizeof( struct CMessage );
     cmess.cn_Message.mn_Node.ln_Name= "cstuff";

     if( cport->ack != 30 )
          {    
          cport->ack = 1;
          goto EXIT;
          }

     cport->ack = 0;

/*****************************
Setup Our Pointers To Point To
Cnets Internal Data Structures
*****************************/
 
     PORTDATA    = cport->zp;
     MAINPORT    = cport->myp;
     SEM         = MAINPORT->SEM;
     bm          = PORTDATA->bm;
     Subboard    = PORTDATA->sb;
     LastCommand = PORTDATA->BackBuff[PORTDATA->bbnum -1];
  if( !(CNetBase = OpenLibrary( "cnet.library",0 )) ) goto EXIT;

/*****************************************************************************/ 
/*
PORTDATA->fib  = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE);
FreeDosObject(DOS_FIB, PORTDATA->fib); ****** Cnet Already Allocates This ****
							    ****** So Didn't Need To Use It... ****/

stci_d (AccNo, PORTDATA->id    );
stci_d (Port,  PORTDATA->InPort);

strmfp (_Free      , Subboard->DataPath, "Data/_Free"     );
strmfp (_Text      , Subboard->DataPath, "Data/_Text"     );
strmfp (_Short     , Subboard->DataPath, "Data/_Short"    );
strmfp (_Items3    , Subboard->DataPath, "Data/_Items3"   );
sprintf(_EdBuff    ,"Ram:_EdBuff%d"    ,  PORTDATA->InPort);
sprintf(_Comment   ,"Uploader: %d %s"  ,  PORTDATA->id, PORTDATA->user1.Handle);
sprintf(_TempBuff  ,"Ram:_TempBuff%d"  ,  PORTDATA->InPort);
strmfp (_Headers3  , Subboard->DataPath, "Data/_Headers3" );
strmfp (_Message3  , Subboard->DataPath, "Data/_Message3" );
strmfp (_DescPath  , Subboard->DataPath, "Data/Descs"     );
strmfp (_FilePath  , Subboard->DataPath,  PORTDATA->Item0.Title); 
strmfp (_DizPath   , PORTDATA->home    , "File_Id.Diz");
strmfn (_LongDesc  , NULL              , _DescPath   , PORTDATA->Item0.Title, "Dsc");

Display_Not = PORTDATA->DoQuick;
if(access(_DescPath , R_OK) !=0) mkdir(_DescPath);

/*********************
 Adopt Orphans Routine
*********************/
if(!stricmp(strupr(argv[2]), "ADOPT"))
     {
	if(!strstr(strupr(Subboard->DataPath), strupr(PORTDATA->myloc)))
          {
          PutText("n1b1Please Enter A UDBase Area First!n1");
          goto EXIT;
          }

	PORTDATA->MyDoing = "Adopting Files";
	DisplayChart ( 4 );
	if(Display_Not)
		{
		Display_Not = FALSE;
		Display(1, " -=MaxSpeed=-", NULL, "Adopting Orphans. Please Wait.");
		Display_Not = TRUE;
		}
	AdoptionDate = PORTDATA->Today;
	NumAdopted   = 0;

	SetAdoptTemplates();
	ReadItems    (   );
	MakeCheckList(   );
	CleanUpLongs (   );
	
	Display(1,  AdoptTitle, NULL                        , "Adopt Orphans.");
	Display(2, "Total"    , Subboard->rn                , "Highest Item /File Serial ID No.");
	Display(3, "Total"    , PORTDATA->mx                , "Online Items In This Subboard.");
	Display(4, "Total"    , Subboard->rn - PORTDATA->mx , "Killed  Items/Files.");
	  
	if(!AskQuestions() ) goto LEAVE;
	if(!UseUploader )Display(3, "Adopted Acc#/Handle", PORTDATA->id, PORTDATA->user1.Handle);
	Display(5, "Working..", NULL, NULL);
	ItemID = Subboard->rn;
	lock   = Lock(Subboard->DataPath,ACCESS_READ);
	Examine(lock,PORTDATA->fib);       
	do
	     {
	     if(ItemID > Subboard->MaxItems || ItemID > PORTDATA->nips)
	          {
	          Display(5, "Max. Items Exceeded!", Subboard->MaxItems, "Increase MaxItems For Subboard.g0");
	          goto LEAVE;
	          }
	     if(WaitForInput(10)) 
	          {
	          Display(5, "Abort Requested", NULL, "Cleaning Up.");   
	          PutText("b1");
	          goto LEAVE;
	          }
	     Display(1, "  Dir Scan.", NULL, PORTDATA->fib->fib_FileName);
	     if(PORTDATA->fib->fib_DirEntryType<0)
	          {
	          if(!strstr(CheckList, strupr(PORTDATA->fib->fib_FileName)))
                    {
				strmfn (_LongDesc, NULL, _DescPath   , PORTDATA->fib->fib_FileName, "Dsc");
	               strmfp (_FilePath, Subboard->DataPath, PORTDATA->fib->fib_FileName);
				if(!strstr(PORTDATA->fib->fib_Comment, "Uploader:")) SetComment(_FilePath, _Comment);
				if(UseUploader)
					{
					if(!(PORTDATA->Header0.ByAccount = CommentToAccount( &PORTDATA->user2,  PORTDATA->fib->fib_Comment)))
						{
						memcpy(&PORTDATA->user2, &PORTDATA->user1, sizeof(struct UserData));
						PORTDATA->Header0.ByAccount = PORTDATA->id;
						}
					else
						{
	                    	strcpy(PORTDATA->Header0.By        , PORTDATA->user2.RealName);
	                    	strcpy(PORTDATA->Header0.ByUser    , PORTDATA->user2.Handle  );
	                    	       PORTDATA->Header0.ByID      = PORTDATA->user2.IDNumber;
	                    	       PORTDATA->  Item0.ByID      = PORTDATA->user2.IDNumber;
	                    	       PORTDATA->  Item0.ByAccount = PORTDATA->Header0.ByAccount;                    
	                    	}
					}
	               ItemID     ++;
				NumAdopted ++;
	               if(!(mh[ItemID] = lsbrk(sizeof(struct HeaderType))))
	                    {
	                    Display(2,"Memory Error.", sizeof(struct HeaderType), "Bytes Cannot be Allocated");
	                    goto LEAVE;
	                    }
				if( UseDosDates)  GetFileDate( PORTDATA->fib->fib_Date);
	               else              Display(4,"Adopted Date/Time", 0, "V1500000}f0");
	               
	               if(UseFile_ID)
	                    {
	                    if(PORTDATA->txline = GetDiz( _EdBuff, _FilePath )) SaveDescription( );
	                    else { Display(1, "File_Id.Diz", NULL, "Not Available.");  PORTDATA-> Item0.Described = FALSE; }
	                    }

	               strcpy( PORTDATA ->   Item0.Title        ,  PORTDATA->fib->fib_FileName);
	               if(   ! PORTDATA ->   Item0.Described)      Desc_Not    ++;
					   PORTDATA ->   Item0.ByteDownload =  PORTDATA->fib->fib_Size;
					   PORTDATA ->   Item0.FileDownload =  1;
	                       PORTDATA ->  ihead0.Size         =  PORTDATA->fib->fib_Size;
	                       PORTDATA ->  ihead0.Number       =  ItemID;
	               memcpy( PORTDATA ->  ihead0.TitleSort    ,  PORTDATA->fib->fib_FileName, 9);             
	                       PORTDATA ->  ihead0.PostDate     =  AdoptionDate;
	                       PORTDATA ->  ihead0.RespDate     =  AdoptionDate;
	                       PORTDATA -> Header0.PostDate     =  AdoptionDate;
	                       PORTDATA -> Header0.EditDate     =  AdoptionDate;
	                       PORTDATA -> Header0.ShowDate     =  AdoptionDate;

	               if(PORTDATA -> ih[ItemID]) memcpy( PORTDATA -> ih[ItemID] , &PORTDATA-> ihead0,  sizeof(struct ItemHeader));
	               if(PORTDATA -> ip[ItemID]) memcpy( PORTDATA -> ip[ItemID] , &PORTDATA->  Item0,  sizeof(struct ItemType3 ));
	               if(            mh[ItemID]) memcpy(             mh[ItemID] , &PORTDATA->Header0,  sizeof(struct HeaderType));
	               Display(2, "Total", NumAdopted , "Adopted Items Added.");
				Display(3, "Adopted Acc#/Handle", PORTDATA->Header0.ByAccount, PORTDATA->Header0.ByUser);
	               Display(5, "Adopted File/Size", PORTDATA->fib->fib_Size, PORTDATA->fib->fib_FileName);
	               }                  
	          }
	     }
	     while(ExNext(lock, PORTDATA->fib)!=0 );
          
LEAVE:

     UnLock ( lock );
     free(CheckList);
	if(NumAdopted) SaveItems();
	free(mh);
	_MemCleanup();
	if(Display_Not)     {  Display_Not = FALSE ;  DisplayChart(4);  }
	Display(1, "  Completed", NULL  , "Coded By MadMax -=Radiance=-");
	Display(2, "Total", NumAdopted             , "Newly Adopted Files.");
	Display(3, "Total", Desc_Not               , "Adopted Items Need Describing.");
	Display(4, "Total", PORTDATA->mx           , "Online Items In This Subboard.");
	Display(5, "Total", Subboard->rn           , "Actual Items By Serial ID No.");				
     goto EXIT;
     }

if(!stricmp(strupr(argv[2]), "EDIT"))
     {
	PORTDATA->ScreenWidth = 44;
     sprintf(OtTxt,"f1n2%-41s", PORTDATA->Item0.Title);
     PutText(OtTxt);
     MAINPORT -> gc.MaxShortLines = 30;
     PORTDATA -> user1.DefEditor  = 1;
     if(PORTDATA->Item0.Described == TRUE)
          {
          if(InFileA = fopen(_EdBuff,"r"))
               {  
               fscanf(InFileA, "%s%s", Suff, _DescPath);
               fclose(InFileA);
               if(strstr(Suff,"*0"))
                    {
                    ReplaceText(_DescPath,"}","");
                    COPY(_DescPath, _EdBuff, DelBits, "w");
                    goto EXIT;
                    }
               }
          }
          else 
               {
               if(!access(_FilePath, R_OK))
                    {
                    DisplayChart(0);
                    GetDiz( _EdBuff, _FilePath );
                    }
               }
          PORTDATA -> txline      = 0;
		PORTDATA -> ScreenWidth = PORTDATA->user1.TermWidth;
          goto EXIT;
     }


if(!stricmp(strupr(argv[2]), "SAVE"))
     {
     OtFileA = fopen(_EdBuff,"w");
     for(i=0; i<PORTDATA->txline-1; i++)
          {
          fprintf(OtFileA, "%s\n", PORTDATA->EdBuffer[i]);
          }
     fprintf(OtFileA, "%s", PORTDATA->EdBuffer[i]);
     fclose (OtFileA);
     if(PORTDATA->txline>=8)
          {
          sprintf(PORTDATA->EdBuffer[0], "*0 %s}", _LongDesc);
          PORTDATA->txline = 1;
          COPY(_EdBuff, _LongDesc, AddBits, "w");
          }
     MAINPORT   ->gc.MaxShortLines = 8;
     PORTDATA   ->user1.DefEditor  = 0;
     if(PORTDATA->user1.not_used2 == FALSE && !PORTDATA->Item0.Described)
          {
          DisplayChart(0);
          AddDiz( _EdBuff, _FilePath );
          PutText("n2");
          }
     remove(_EdBuff);
     goto EXIT;
     }

/*****************************
 Uploads File_Id Processing.
*****************************/

if(strstr(strupr(LastCommand),"D")) goto EXIT;
DisplayChart( 1 );
if(Display_Not)
		{
		Display_Not = FALSE;
		Display(1, " -=MaxSpeed=-", NULL, "File_Id Processing. Please Wait.");
		Display_Not = TRUE;
		}
PORTDATA->MyDoing = "Describing Uploads";
for (i=0; i<=PORTDATA->NoUploaded-1; i++)
     {
     if(InFileA = fopen(_Items3,"r"))
          {
          fseek(InFileA, (((PORTDATA->Upload[i].Number)-1) * sizeof(struct ItemType3)), SEEK_SET);
          fread(&PORTDATA->Item0, sizeof(struct ItemType3), 1, InFileA);
          fclose(InFileA);    
          }
     strmfn (_LongDesc, NULL, _DescPath, PORTDATA->Upload[i].Title, "Dsc");
     strmfp (_FilePath, Subboard->DataPath, PORTDATA->Upload[i].Title);
     SetComment(_FilePath, _Comment);
     Display(2, "Describing.", GetFileSize(_FilePath), PORTDATA->Upload[i].Title);
     Display(1, "Scanning"   , NULL                  , "For File_Id.Diz"        );
     if(PORTDATA->ip[PORTDATA->Upload[i].Number -1]->Described == FALSE)
          {
          if(PORTDATA->txline = GetDiz( _EdBuff, _FilePath )) SaveDescription( );
          else Display(1, "File_Id.Diz", NULL, "Not Available.");
          }
     else Display(1, "Scanning", NULL, "File Pre-Described");
     memcpy(PORTDATA->ip[PORTDATA->Upload[i].Number -1], &PORTDATA->Item0, sizeof(struct ItemType3));
     }
     Display(1, "  Completed.", NULL, "");
     remove(_EdBuff);
     PORTDATA->txline = 0;
     Display(2, "Total", PORTDATA->NoUploaded, "Uploaded Items"); 

EXIT:     PutText("c7n2");
          ShutDown( NULL );
          DeletePort( replyp );
          if( CNetBase) CloseLibrary( CNetBase );
          exit(0);
}


/************************[ MAIN PROGRAM END ]**************************************/


/*****************************************************************************
Attempts To Extrapolate Original File Uploaders Details From File Comment....
Returns NULL If Uploaders Details Cannot Be Extracted.
*****************************************************************************/

int CommentToAccount( struct UserData *MyData, char *Comment)

{
     char Check[10];
     int  Account = 0;
     sscanf(Comment, "%s%s", Check, AccNo);
     if(strstr(Check,"Uploader:"))
          {
          strcat(AccNo,"!");
          Account = FindAccount(AccNo, MyData);
          }
     else SetComment(_FilePath, _Comment);

return(Account);
}


/*****************************************************************************
Bulk Saves Cnet's ItemHeader/ItemType/HeaderType Buffers & Updates Cnet's
Subboard Pointers & Sets A Flag To Tell Cnet To Re-Organising The Buffers.
Also Error/Retry On Writing DataFiles If Another Node Is Writing To Them.
*****************************************************************************/

void SaveItems( void )

{
     FILE *InFileA;
     FILE *OtFileA;
     FILE *OtFileB;
     FILE *OtFileC;
     FILE *OtFileD;
     int c   = 0;
     int Err = 0;

     strmfp (_Text, Subboard->DataPath, "Data/_Text");
     strmfp (_Free, Subboard->DataPath, "Data/_Free");
     Display(1, " Updating", NULL, "_Text, _Items3 & _Headers3 Files.");
     Subboard->free0 = lsbrk( 4 * sizeof(struct FreeType));
     setmem(Subboard->free0,  4 * sizeof(struct FreeType), 0);
     if(access(_Free,R_OK)!=0)
          {
          OtFileA = fopen(_Free,"w");
          fwrite(Subboard->free0, sizeof(struct FreeType)-4, 1, OtFileA);
          fclose(OtFileA);
          }
     if(access(_Text,R_OK)!=0)
          {
          OtFileA = fopen(_Text,"w");
          fclose(OtFileA);
          }
     else
          {
          if(InFileA = fopen(_Free,"r"))
               {
               fread(Subboard->free0, sizeof(struct FreeType)-4, 1, InFileA);
               fclose(InFileA);
               }
          }
     do
          {
          if(Err)
               {
               if(!Display_Not) Display(2, "File Error.", Err, "Retry Writing DataFiles");
               else { sprintf(OtTxt,"n1z4Error Writing DataFiles:z0 Retry %dn1^2", Err); PutText(OtTxt);}
               }
          
          if(OtFileA  = fopen(_Items3  , "a" ))
               {
               if(OtFileB  = fopen(_Headers3, "a" ))
                    {
                    if(OtFileC  = fopen(_Text    , "r+"))
                         {
                         if(OtFileD  = fopen(_Message3, "a" ))
                              {
                              fseek(OtFileC, Subboard->free0->start, SEEK_SET);
                              for(c=Subboard->rn+1; c <= ItemID; c++)
                                   {
							Subboard->count++;
                                   PORTDATA->ip[c]->First        = Subboard->free0->start;
                                   PORTDATA->ip[c]->Last         = Subboard->free0->start;
                                   PORTDATA->ih[c]->Number       = Subboard->count;
                                   PORTDATA->Message0.ItemNumber = Subboard->count;
                                   PORTDATA->Message0.ByID       = PORTDATA->ip[c]->ByID;
                                   PORTDATA->Message0.PostDate   = PORTDATA->ih[c]->PostDate;
                                   fwrite( PORTDATA->   ip[c], sizeof(struct ItemType3 )  , 1, OtFileA);
                                   fwrite( PORTDATA->   ih[c], sizeof(struct ItemHeader)  , 1, OtFileB);
                                   fwrite(              mh[c], sizeof(struct HeaderType)  , 1, OtFileC);
                                   fwrite(&PORTDATA->Message0, sizeof(struct MessageType3), 1, OtFileD);
                                   free(  mh[c]);                         
                                   Subboard->free0->start  = Subboard->free0->start  + sizeof(struct HeaderType);
                                   Subboard->free0->length = Subboard->free0->length - sizeof(struct HeaderType);
                                   }
                              fclose(OtFileD);
                              }
                         fclose(OtFileC);
                         }
                    fclose(OtFileB);
                    }
               fclose(OtFileA);
               }
           if(!c) { Err ++; Delay (60);}
           }
     while(c <= ItemID && Err < 11);
     if(!Err)
          {
          
          if(Subboard->free0->length <= 0)
               {
               Pad_Text(206 );
               Subboard->free0->length = (GetFileSize(_Text) - Subboard->free0->start);
               }
          if(OtFileA = fopen(_Free,"w"))
               {
               fwrite(Subboard->free0, sizeof(struct FreeType)-4, 1, OtFileA);
               fclose(OtFileA);    
               }
		Subboard->nm = Subboard->nm + NumAdopted;
          Subboard->rn = Subboard->rn + NumAdopted;
          PORTDATA->mx = PORTDATA->mx + NumAdopted; 
          Subboard->     resetIP++;
          }
     else
          {
          NumAdopted   = 0;
          Desc_Not     = 0;
          }
}

/*****************************************************************************
Pads Out The _Text Data File With (Num * sizeof(HeaderType)) Blocks
*****************************************************************************/

void Pad_Text( int Num )

{
     FILE *OtFile;
     int i = 0;
     setmem(&PORTDATA->Header0, sizeof(struct HeaderType), 0);
     OtFile = fopen(_Text,"a");
     for(i  = 0; i < Num; i++)
         {    
         fwrite(&PORTDATA->Header0, sizeof(struct HeaderType), 1, OtFile);
         }
     fclose(OtFile);
}

/*****************************************************************************
Asks User Questions On How Files Are To Be Adopted.  Uses MCI `?n' Methods.
*****************************************************************************/

int AskQuestions( void )

{
     char Settings[34];
     char *Quote = "<15}   c7[c3Yc7/c3Nc7]:>6c2   <3?0f0";
     int Abort = 0;
     if(!strstr(LastCommand, "!"))
          {
          DisplayHelp("File_Id.Diz Descriptions Will Be Used If Located.", "All Items Will Be Adopted Without Descriptions.");
          Display(5, "Adopt File_Id.Diz's ", NULL, Quote);
          stcd_i(PORTDATA->MCIcreg[0], &UseFile_ID);
          if(UseFile_ID) strcpy(Settings,"File_ID's:");
          else           strcpy(Settings,"No Desc's:");
          Display(1, " Settings...." , NULL, Settings);
          DisplayHelp("Dates Will Be Taken From Each Files DateStamp.", "All Dates Will Be Set To Todays Date.");
          Display(5, "Adopt Dos FileDates.", NULL, Quote);
          stcd_i(PORTDATA->MCIcreg[0], &UseDosDates);
          if(UseDosDates) strcat(Settings," File Dates:");
          else            strcat(Settings," TodaysDate:");
          Display(1, " Settings...." , NULL, Settings);
          DisplayHelp("If Available, Adopt Files Using Original Uploaders Details.", "Adopt Files Using You're Own Details.");
          Display(5, "Original Uploader.", NULL, Quote);
          stcd_i(PORTDATA->MCIcreg[0], &UseUploader);
          if(UseUploader) strcat(Settings," By Uploader");
          else            strcat(Settings," By Adopter");
          Display(1, " Settings....", NULL, Settings);
          DisplayHelp("Continue With Adopting Orphans.","Abort Now.");
          Display(5, "Okey To Continue", NULL,     Quote);
          stcd_i(PORTDATA->MCIcreg[0], &Abort);
          DisplayHelp("","");
          }
     else
          {
          UseFile_ID = 0; UseDosDates= 0; Abort = 1; UseUploader = 0;
          }
     return( Abort );
}

/*****************************************************************************
Fills Out A CheckList Buffer With All Online FileNames. This Is Then Used When 
Directory Scanning To Check If Files Are Already Online Or Not........
*****************************************************************************/

void MakeCheckList( void )

{
     int i = 0;
     CheckList  = lsbrk(Subboard->rn * 42);
     setmem(CheckList, sizeof(CheckList), 0);
     for(i = 0; i< Subboard->rn; i++)
          {
          if(!PORTDATA->ih[i]->Killed)
          strcat(CheckList, strupr(PORTDATA->ip[i]->Title));
          }
}

/*****************************************************************************
Checks For Any Old Long Descriptions That Are No Longer In Use. Checking Done
Through Directory Scan Check Against CheckList Buffer Created Above..........
*****************************************************************************/

void CleanUpLongs( void )
{
char KillFile[60];
     Display(1, " Checking...." , NULL, "Removing Old Long Descriptions.");
     lock = Lock(_DescPath,ACCESS_READ);
     Examine(lock,PORTDATA->fib);       
     do
          {
          if(PORTDATA->fib->fib_DirEntryType<0)
               {
               strmid(PORTDATA->fib->fib_FileName, KillFile, 1, strlen(PORTDATA->fib->fib_FileName)-4);
               if(!strstr(CheckList, strupr(KillFile)))
                    {
                    strmfp(KillFile, _DescPath, PORTDATA->fib->fib_FileName);
                    remove(KillFile);
                    }
               }
          }
     while(ExNext(lock, PORTDATA->fib)!=0);
     UnLock ( lock );
}
/*****************************************************************************
Displays A Blank Chart Of `Num' Rows Ready For Accepting Data Using Display()
*****************************************************************************/  

void DisplayChart( int Num )
{
	if(Display_Not) Num = 0;
     PutText("f1c7");
     PutText("n1ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
     PutText("n1³z4MaxDiz V2.0 Beta Test z0³              ³                                     ³");
     if(Num)
          {
          do
               {
               Num--;
               PutText("n1ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´");
               PutText("n1³                      ³              ³                                     ³");
               }
          while(Num);
          }
     PutText("ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
}
/******************************************************************************
Puts Info Into The Display Chart For You.  Heavy On The MCI Curser Positioning!
******************************************************************************/

void Display( int Line, char *Item1, long Item2, char *Item3)

{
if(!Display_Not)
     {
     if(Line == 1) sprintf(FmtStr,"f0n%d}>24}c3%-14s>2c2%-34sc7", Line*2, Item1, Item3);
     else          
     sprintf(FmtStr,"f0n%d}>2c6%-21s>2c3%-13d>2c2%-34sc7", Line*2, Item1, Item2, Item3);
     PutText(FmtStr);
     }
}

void DisplayHelp( char *Item1, char *Item2 )
{
char HelpText[200];
if(!Display_Not)
     {
     if(strlen(Item1)<1)
     sprintf(HelpText,"f0n13}%-70sn1%-70s", Item1, Item2);
     else
     sprintf(HelpText,"f0n13}c7[c3Yc7] = %-70sn1c7[c3Nc7] = %-70s", Item1, Item2);
     PutText(HelpText);
     }
}


/****************************************************************************
There's Gotta Be A Quicker/Shorter Way Of Converting Amiga DateStamps To 
Cnet's `struct IsDate' BYTE Date Storage format.  I Dunno How Though :(...
****************************************************************************/

void GetFileDate( struct DateStamp MyDateStamp )

{
struct DateTime FileDate;
char Dt_Tm [50];
char CMonth[3];
char CDay  [3];
char CYear [3];
char CHours[3];
char CMins [3];
char CSecs [3];
char SDay  [10];
char SDate [10];
char STime [10];
int  Day   = 0;
int  Year  = 0;
int  Month = 0;
int  Hour  = 0;
int  Mins  = 0;
int  Secs  = 0;

     FileDate.dat_Stamp   = MyDateStamp;
     FileDate.dat_Format  = FORMAT_DOS;
     FileDate.dat_Flags   = 0;
     FileDate.dat_StrDate = SDate;
     FileDate.dat_StrTime = STime;
     FileDate.dat_StrDay  = SDay;
     if(DateToStr(&FileDate))
          {
          sprintf(Dt_Tm, "c7%-10sc3%-11sc6%-10s", FileDate.dat_StrDay, FileDate.dat_StrDate, FileDate.dat_StrTime); 
          Display(4, "Adopted Date/Time", NULL, Dt_Tm);
          FileDate.dat_Format  = FORMAT_USA;
          if(DateToStr(&FileDate))
               {
               ReplaceText(FileDate.dat_StrDate, "-", " ");
               ReplaceText(FileDate.dat_StrTime, ":", " ");
               sscanf(FileDate.dat_StrDate,"%s%s%s", CMonth, CDay , CYear);
               sscanf(FileDate.dat_StrTime,"%s%s%s", CHours, CMins, CSecs);
               stcd_i(CMonth, &Month );
               stcd_i(CDay  , &Day   );
               stcd_i(CYear , &Year  );
               stcd_i(CHours, &Hour  );
               stcd_i(CMins , &Mins  );
               stcd_i(CSecs , &Secs  );
               AdoptionDate.Year  = (BYTE)Year;
               AdoptionDate.Month = (BYTE)Month;
               AdoptionDate.Date  = (BYTE)Day;
               AdoptionDate.Hour  = (BYTE)Hour;
               AdoptionDate.Minute= (BYTE)Mins;
               AdoptionDate.Second= (BYTE)Secs;
               }
          }
}

/*****************************************************************************
Fills Out Template Ready For Use On Newly Adopted Files.
*****************************************************************************/

void SetAdoptTemplates ( void )

{
     setmem(&PORTDATA->Message0, sizeof(struct MessageType3), 0);
     PORTDATA        ->Message0.ItemNumber = Subboard->count+1;
     PORTDATA        ->Message0.ByID       = PORTDATA->user1.IDNumber;
     PORTDATA        ->Message0.ToID       = 0;
     PORTDATA        ->Message0.PostDate   = AdoptionDate;
     PORTDATA        ->Message0.IsFile     = TRUE;

     setmem(&PORTDATA->Header0, sizeof(struct HeaderType), 0);
     PORTDATA        ->Header0.ShowDate    = AdoptionDate;
     PORTDATA        ->Header0.EditDate    = AdoptionDate;
     PORTDATA        ->Header0.PostDate    = AdoptionDate;
     PORTDATA        ->Header0.ByAccount   = PORTDATA->id;
	PORTDATA        ->Header0.Number      = 1;
     PORTDATA        ->Header0.ByID        = PORTDATA->user1.IDNumber; 
     strcpy(PORTDATA ->Header0.NetAddress  , PORTDATA->user1.UUCP    );
     strcpy(PORTDATA ->Header0.By          , PORTDATA->user1.RealName);
     strcpy(PORTDATA ->Header0.ByUser      , PORTDATA->user1.Handle  );
     strcpy(PORTDATA ->Header0.Organ       , PORTDATA->user1.Organ   );

     setmem(&PORTDATA->Item0, sizeof(struct ItemType3), 0);             
     PORTDATA        ->Item0.ByID          = PORTDATA->user1.IDNumber;
     PORTDATA        ->Item0.ToID          = NULL;                    
     PORTDATA        ->Item0.Finished      = TRUE;                    
     PORTDATA        ->Item0.Validated     = TRUE;
     PORTDATA        ->Item0.ByAccount     = PORTDATA->id;
     PORTDATA        ->Item0.PurgeStatus   = Subboard->PurgeStatus;
     PORTDATA        ->Item0.DLnotifyULer  = Subboard->DLnotifyULer;
     PORTDATA        ->Item0.PleaseKill_NOT= FALSE;
     PORTDATA        ->Item0.PurgeKill     = TRUE;
     PORTDATA        ->Item0.loaded        = FALSE;

     setmem(&PORTDATA->ihead0, sizeof(struct ItemHeader), 0);
     PORTDATA        ->ihead0.Number       = Subboard->count+1;
     PORTDATA        ->ihead0.PostDate     = AdoptionDate;
     PORTDATA        ->ihead0.RespDate     = AdoptionDate;
     PORTDATA        ->ihead0.Killed       = FALSE;
     PORTDATA        ->ihead0.Responses    = 0;
}

/*****************************************************************************
Reads In Available Items And Headers Into Cnets FileList Buffers & Stores No.
Of Items In Subboard->rn & No. Items_NotKilled In PORTDATA->mx
*****************************************************************************/

void ReadItems( void )
{
FILE *InFileA;
FILE *InFileB;
int   OKa = 0;
int   OKb = 0;

     PORTDATA->mx = 0;
     Subboard->rn = 0;
     if(InFileA = fopen(_Items3,"r"))
          {
          if(InFileB = fopen(_Headers3,"r"))
               {
               Display(1, " Re-Loading.", NULL, "Subboard's DataFiles.");
               do
                    {
                    if(OKa = fread(PORTDATA->ip[Subboard->rn], sizeof(struct ItemType3) , 1, InFileA))
                         {
                         if(OKb = fread(PORTDATA->ih[Subboard->rn], sizeof(struct ItemHeader), 1, InFileB))
                              {
                              PORTDATA->ihead0.Number = PORTDATA->ih[Subboard->rn]->Number;
                              if(!  PORTDATA->ih[Subboard->rn] ->Killed) PORTDATA->mx++;
                              Subboard->rn++;
                              }
                         }
                    }
               while(OKa && OKb);
               fclose(InFileA);
               }
          fclose(InFileB);
          }
}

/********************************************************************
Calulates Description Pointers And Writes Description To _Short File.
********************************************************************/

void SaveDescription( void )

{
     Display(1, " File_Id.Diz", NULL, "Located.");
     PORTDATA->Item0.Described = TRUE;
     if(PORTDATA->txline >= 8)
          {
          sprintf(OtTxt,"*0 %s}", _LongDesc);
          OtFileA = fopen(_Short,"a");
          fwrite (OtTxt, strlen(OtTxt)+1, 1, OtFileA);
          fclose (OtFileA);
          COPY(_EdBuff, _LongDesc, AddBits, "w");
          PORTDATA->Item0.InfoX     = (GetFileSize(_Short)-strlen(OtTxt)-1);
          PORTDATA->Item0.InfoLen   = strlen(OtTxt)+1;
          }
     else
          {
          DSize = COPY(_EdBuff, _Short, Normal, "a");
          PORTDATA->Item0.InfoX     = ((GetFileSize(_Short)-DSize)-1);
          PORTDATA->Item0.InfoLen   = DSize+1;
          }
}

int GetDiz( char *_EdBuff, char *_FilePath )

/*******************************************************************
Locates File_Id.Diz.  If Located,  Description File  = `_EdBuff' &
Returns Number Of Lines In Description In PORTDATA->txline.  If A
File_Id.Diz Is Not Located, PORTDATA->txline Will == 0.
*******************************************************************/

{
FILE *InFile;
FILE *OtFile;
char Suff[5];
     
     remove(_EdBuff);
     Display(1, " Scanning", NULL, "For File_ID.Diz");
     PORTDATA->txline = 0;
     strmid (_FilePath, Suff, strlen(_FilePath)-3, strlen(_FilePath));

     if(!stricmp(Suff,".DMS"))
          {
          sprintf(OtTxt,"Pfiles:MaxDiz2/DmsDiz x %s %s", _EdBuff, _FilePath);
          Execute(OtTxt, NULL, NULL);
          }

     if(!stricmp(Suff,".LHA"))
          {
          sprintf(OtTxt,"Pfiles:MaxDiz2/Lha x %s File_Id.Diz %s", _FilePath, PORTDATA->home);
          Execute(OtTxt, NULL, NULL);
          COPY( _DizPath, _EdBuff, Normal, "w");
          }
     
     if(!stricmp(Suff,".ZIP"))
          {
          chdir(PORTDATA->home);
          sprintf(OtTxt,"Pfiles:MaxDiz2/unzip -oqq %s File_Id.Diz", _FilePath);
          Execute(OtTxt, NULL, NULL);
          COPY( _DizPath, _EdBuff, Normal, "w");
          }

     if(!stricmp(Suff,".DOC")||!stricmp(Suff,".TXT")||!stricmp(Suff,".NFO")||!stricmp(Suff,".DOK")||!stricmp(Suff,".DOX"))
          {
          sprintf(OtTxt,"Pfiles:MaxDiz2/txtdiz %s %s", _FilePath, _EdBuff);
          Execute(OtTxt, NULL, NULL);
          }
     if(!stricmp(Suff,".EXE"))
          {
          chdir("ram:");
          sprintf(OtTxt,"Pfiles:MaxDiz2/ExeDiz x %s %s", _EdBuff, _FilePath);
          Execute(OtTxt, NULL, NULL);
          }
     setmem(OtTxt, sizeof(OtTxt), 0);
     if(InFile = fopen(_EdBuff,"r"))
          {
          PORTDATA->user1.not_used2 = TRUE;
          OtFile = fopen(_TempBuff, "w");
          do
               {
               if(strlen(stpblk(OtTxt))>1)
                    {
                    fprintf(OtFile, "%s", OtTxt);
                    PORTDATA->txline++;
                    }
               }
          while(fgets(OtTxt, sizeof(OtTxt), InFile));
          fseek(OtFile, -1, SEEK_CUR);
          putc(13,OtFile);
          fclose(InFile);
          fclose(OtFile);
          remove(_EdBuff);
          rename(_TempBuff, _EdBuff);
          }
     else PORTDATA->user1.not_used2 = FALSE;
return( PORTDATA->txline );

}

/*****************************************************************************/

void AddDiz( char *_EdBuff, char *_FilePath )

{
     strmid (_FilePath, Suff, strlen(_FilePath)-3, strlen(_FilePath));
     Display(1, "   Adding."   , NULL, "New File_Id.Diz Description");
     if(!stricmp(Suff,".DMS"))
          {
          Display(1, "  Working."   , NULL, "Cleaning Up Archive");
          sprintf(OtTxt,"Pfiles:MaxDiz2/DmsDiz d %s", _FilePath);
          Execute(OtTxt, NULL, NULL);
          sprintf(OtTxt,"Pfiles:MaxDiz2/DmsDiz a %s %s", _EdBuff, _FilePath);
          Execute(OtTxt, NULL, NULL);
          }
     if(!stricmp(Suff,".LHA"))
          {
          COPY(_EdBuff, _DizPath, Normal, "w");
          sprintf(OtTxt,"Pfiles:MaxDiz2/Lha  r %s %s", _FilePath, _DizPath);
          Execute(OtTxt, NULL, NULL);
          }
     if(!stricmp(Suff,".ZIP"))
          {
          COPY(_EdBuff, _DizPath, Normal, "w");
          sprintf(OtTxt,"Pfiles:MaxDiz2/Zip %s %s", _FilePath, _DizPath);
          rename (_EdBuff, "Ram:File_Id.Diz");
          Execute(OtTxt, NULL, NULL);
          }
     if(!stricmp(Suff,".DOC")||!stricmp(Suff,".TXT")||!stricmp(Suff,".NFO")||!stricmp(Suff,".DOK")||!stricmp(Suff,".DOX"))
          {
          COPY(_FilePath, _DizPath, Normal, "w"); 
          sprintf(OtTxt,"Pfiles:MaxDiz2/TxtDiz %s %s -f %s", _DizPath, _FilePath, _EdBuff);
          Execute(OtTxt, NULL, NULL);
          remove(_DizPath);
          }
     remove(_EdBuff);
}


/*****************************************************************************/

int COPY( char *From, char *To, int Action, char *Mode)

/****************************************************************
COPY <From> <To> <AddBits|DelBits|Normal> <"r"|"w"|"a"|"r+"|"w+">
****************************************************************/

{
char   *Buffer;
FILE   *InFile;
FILE   *OtFile;


     if(!access(From, R_OK))
          {
          DSize  = GetFileSize(From);
          Buffer = lsbrk(DSize);
          InFile = fopen(From,"r");
          if(Action == DelBits)
               {
               fseek(InFile, 41, SEEK_SET);
               DSize = DSize - 42;
               }
          fread(Buffer, DSize, 1, InFile);
          fclose(InFile);
          ReplaceText(Buffer, "", "{");
          OtFile = fopen(To,Mode);
          if(Action == AddBits)
               {
               fwrite("                                   :2^1",41,1, OtFile);
               fwrite(Buffer, DSize, 1, OtFile);
               DSize = DSize + 41;
               putc(0 , OtFile);
               }
          if(Action == Normal)
               {
               fwrite(Buffer, DSize, 1, OtFile);
               putc(0, OtFile);
               }
          if(Action == DelBits)
               {
               fwrite(Buffer, DSize, 1, OtFile);
               putc(13, OtFile);
               }
          fclose(OtFile);
          free(Buffer);
          }
     return( DSize );
}

/*****************************************************************************/

long GetFileSize( char *Path )

/******************************
Returns FileSize Of char *Path.
******************************/
{
long FileSize = 0;

if(!access(Path, R_OK))
     {
     stat(Path, &FileStats);
     FileSize = FileStats.st_size;
     }
return ( FileSize );
}
/*****************************************************************************/


void ShutDown( char *spawn )

/***************************************
Detaches This Program From Cnets C Port.
***************************************/
{
     if( spawn ) strcpy( PORTDATA->CSpawn, spawn );
     CallHost( 0 );
}

             
void CallHost( UBYTE c )

/****************************
Sends Command To Cnet C Port.
****************************/

{
     cmess.command = c;
     PutMsg  ( (struct MsgPort *)cport, (struct Message *)&cmess );
     WaitPort( replyp );
     GetMsg  ( replyp );
}


void PutText( char *text )

/**************************************************
Prints text To Screen Without  LineFeed Terminator.
**************************************************/

{
     cmess.arg1 = (ULONG)text;
     CallHost(1);   
}

int EnterLine( UBYTE len, USHORT flags, char *prompt )

/************************************************************
Simply Gets User Input.  Result Located At PORTDATA->InBuffer
************************************************************/

{
     cmess.arg1 = (ULONG)len; /* how many chars max to input     */
     cmess.arg2 = (ULONG)flags;    /* 1=UpperCase           */
     cmess.arg3 = (ULONG)prompt;   /* text to print before input */
     CallHost( 2 );           /* result is in PORTDATA->InBuffer */
     return( (int)strlen( PORTDATA->InBuffer ));
}


char WaitForInput( long mics )
{
     cmess.arg1 = (ULONG) mics;
     CallHost( 31 );
     return( (char)cmess.result );
}

short FindAccount( char *a, struct UserData *b )
{
     cmess.arg1 = (ULONG)a;
     cmess.arg2 = (ULONG)b;
     CallHost( 20 );
     return( (short)cmess.result );
}
