⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syncserver.c

📁 同步软件源码,作者 Jeroen C. Kessels Internet Engineer
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
    SyncServer  --  Server couterpart of SyncUpload.

    >>> SYNCHRONIZE
    <<< CHALLENGE random
    >>> LIST password path
    <<< OK, HERE IS THE LIST:
        date size path                             Date is YYYYMMDDHHMMSS
        date size path
        .
    >>> UPDATE password date size path            Date is YYYYMMDDHHMMSS
    <<< OK, SEND THIS FILE.
    >>> binarydata
        CHECKSUM checksum
    <<< OK, FILE RECEIVED AND STORED.
    >>> DELETE password path
    <<< OK, FILE DELETED.
    >>> QUIT
    <<< OK, CLOSING CONNECTION.

    <<< ERROR: ....message....




    Copyright:   Jeroen C. Kessels
    Date:        19 august 2005
    Version:     4.*

*/




#include "version.h"

#include <stdio.h>
#include <time.h>
#include <io.h>                                   /* isatty() */
#include <winsock2.h>
#include <process.h>
#include <sys/utime.h>
#include <sys/stat.h>
#include <direct.h>

#include "md5.h"
#include "common.h"





/* General constants and variables. */
#define RUNNING  0
#define STOPPING 1
#define STOPPED  2

#define WS_VERSION_REQD 0x0101         /* The minimum winsock version required. */

int Console = NO;                      /* If running as a console program. */

/* Service constants and variables. */
#define SZSERVICENAME        "Kessels SyncServer"   /* Internal name of the service. */
#define SZSERVICEDISPLAYNAME "Kessels SyncServer"   /* Displayed name of the service. */
#define SZDEPENDENCIES       "\0\0"                 /* List of service dependencies - "dep1\0dep2\0\0" */
SERVICE_STATUS        ServiceStatus;   /* Current status of the service. */
SERVICE_STATUS_HANDLE ServiceHandle;   /* From RegisterServiceCtrlHandler(). */

char MyName[BUFSIZ];                   /* Path to this program. */
char CfgPath[BUFSIZ];                  /* Path to the configuration file. */
char LogPath[BUFSIZ];                  /* Path to the logfile. */

/* Listener constants and variables. */
int ServerRunning = STOPPED;
short ServerPort = 9577;               /* The port to listen to. */
int SendTimeout = 120000;              /* Timeout for sending data. */
int ReceiveTimeout = 120000;           /* Timeout for receiving data. */
struct ServerStruct {
  int Running;               /* RUNNING, STOPPING, or STOPPED. */
  int ForceStop;             /* YES or NO. */
  SOCKET ListenSocket;
  SOCKET ReceiveSocket;
  char LocalAddress[16];     /* IP-address of the local end. */
  char RemoteAddress[16];    /* IP-address of the remote end. */
  };






/**** General subroutines ***************************************************/




/* Test if a file exists. Return YES if it does. Normally I would use
   stat() for this, but apparently some implementations of stat() will
   leave some junk on the heap. */
int FileExists(char *Filename) {
  FILE *Fin;

  Fin = fopen(Filename,"r");
  if (Fin == NULL) return NO;
  fclose(Fin);
  return(YES);
  }




/* Create all directories in the path. If IsAdir=NO then the path points
   to a filename, otherwise it is a directoryname. Return YES if succes,
   NO if failure (see ERRNO). */
int CreatePath(char *Path, int IsAdir) {
  char s1[BUFSIZ];
  char *p1;
  int Result;

  if (Path == NULL) return(NO);

  /* Create the directory. Return if succesful. */
  if (IsAdir == YES) {
#ifdef unix
    Result = mkdir(Path,0755);
#else
    /* Do not run mkdir() on the drive designator. */
    if ((strlen(Path) <= 2) && (Path[1] == ':')) return(YES);
    Result = mkdir(Path);
#endif
    if (Result == 0) return(YES);
    }

  /* Strip the highest directory. If there are none then return with NO, creating
     the directory has failed. */
  strcpy(s1,Path);
  p1 = strrchrs(s1,DIRSEP);
  if (p1 == NULL) return(NO);
  *p1 = '\0';

  /* Try to create the lower-level directory. */
  if (CreatePath(s1,YES) == NO) return(NO);

  /* Create the directory. */
  if (IsAdir == NO) return(YES);
#ifdef unix
  Result = mkdir(Path,0755);
#else
  /* Do not run mkdir() on the drive designator. */
  if ((strlen(Path) <= 2) && (Path[1] == ':')) return(YES);
  Result = mkdir(Path);
#endif

  if (Result == 0) return(YES);
  return(NO);
  }





/* Delete everything in the path and it's subdirectories. */
int PathDelete(char *Path) {
  char Path1[BUFSIZ];
  struct stat statbuf;
#ifdef _MSC_VER                  /* Microsoft does not support <dirent.h>. */
  long dirp;
  struct _finddata_t dp;
  #define NAME dp.name
#else
  DIR *dirp;
  struct dirent *dp;
  #define NAME dp->d_name
#endif

  /* If this is a file, then delete it and exit. */
  if ((MyStat(Path,&statbuf) == 0) && ((statbuf.st_mode & 0040000) != 0040000)) {
    if (unlink(Path) != 0) return(NO);
    return(YES);
    }

  /* Walk through the directory, and iterate into subdirectories by calling
     myself. */
#ifdef _MSC_VER
  sprintf(Path1,"%s*",Path);
  dirp = _findfirst(Path1,&dp);
  if (dirp == -1L) return(NO);
  do {
#else
  dirp = opendir(Path);
  if (dirp == NULL) return(NO);
  while ((dp = readdir(dirp)) != 0) {
#endif
    if (strcmp(NAME,".") == 0) continue;
    if (strcmp(NAME,"..") == 0) continue;
    sprintf(Path1,"%s%c%s",Path,*DIRSEP,NAME);
    if (PathDelete(Path1) == NO) {
#ifdef _MSC_VER
      _findclose(dirp);
#else
      closedir(dirp);
#endif
      return(NO);
      }
#ifdef _MSC_VER
    } while (_findnext(dirp,&dp) == 0);
  _findclose(dirp);
#else
    }
  closedir(dirp);
#endif

  if (rmdir(Path) != 0) return(NO);
  return(YES);
  }




/**** Logging ***************************************************************/




/* Translate all special characters in the string. */
void SafeString(char *In, char *Out, int Width) {
  char *p1;
  char *p2;

  p1 = In;
  p2 = Out;
  while ((*In != '\0') && (Width > 1)) {
    if ((*In >= 32) && (*In <= 128)) {
        *Out++ = *In;
        Width--;
      } else {
        if (Width < 5) break;
        sprintf(Out,"[%02X]",*In);
        while (*Out != '\0') {
          Out++;
          Width--;
          }
        }
    In++;
    }
  *Out = '\0';
  }




/* Append a message to the logfile. */
void LogMessage(char *Message) {
  FILE *Fout;
  char s1[BUFSIZ];
  time_t Now;

  time(&Now);
  strcpy(s1,ctime(&Now));
  s1[24] = '\0';

  if (Console == YES) {
    fprintf(stdout,"%s %s\n",s1,Message);
    return;
    }

  if (*LogPath == '\0') return;
  Fout = fopen(LogPath,"a+");
  if (Fout == NULL) return;
  fprintf(Fout,"%s %s\n",s1,Message);
  fclose(Fout);
  }




/**** Error messages ********************************************************/




/* Return a string with the error message for GetLastError(). */
void SystemErrorStr(DWORD ErrorCode, char *Out) {
  char s1[BUFSIZ];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
    NULL,ErrorCode,0,s1,BUFSIZ,NULL);
  sprintf(Out,"error %lu: %s",ErrorCode,s1);
  }




/* Return a string with the error message for WSAGetLastError(). */
void SocketErrorStr(int ErrorCode, char *Out) {
  struct {
    int  ErrorCode;
    char *ErrorText;
    } ErrorArray[] = {
      {WSAEINTR,          "Interrupted system call"},
      {WSAEBADF,          "Bad file number"},
      {WSAEACCES,         "Permission denied"},
      {WSAEFAULT,         "Bad address"},
      {WSAEINVAL,         "Invalid argument"},
      {WSAEMFILE,         "Too many open files"},
      {WSAEWOULDBLOCK,    "Operation would block"},
      {WSAEINPROGRESS,    "Operation now in progress"},
      {WSAEALREADY,       "Operation already in progress"},
      {WSAENOTSOCK,       "Socket operation on non-socket"},
      {WSAEDESTADDRREQ,   "Destination address required"},
      {WSAEMSGSIZE,       "Message too long"},
      {WSAEPROTOTYPE,     "Protocol wrong type for socket"},
      {WSAENOPROTOOPT,    "Bad protocol option"},
      {WSAEPROTONOSUPPORT,"Protocol not supported"},
      {WSAESOCKTNOSUPPORT,"Socket type not supported"},
      {WSAEOPNOTSUPP,     "Operation not supported on socket"},
      {WSAEPFNOSUPPORT,   "Protocol family not supported"},
      {WSAEAFNOSUPPORT,   "Address family not supported by protocol family"},
      {WSAEADDRINUSE,     "Address already in use"},
      {WSAEADDRNOTAVAIL,  "Can't assign requested address"},
      {WSAENETDOWN,       "Network is down"},
      {WSAENETUNREACH,    "Network is unreachable"},
      {WSAENETRESET,      "Net dropped connection or reset"},
      {WSAECONNABORTED,   "Software caused connection abort"},
      {WSAECONNRESET,     "Connection reset by peer"},
      {WSAENOBUFS,        "No buffer space available"},
      {WSAEISCONN,        "Socket is already connected"},
      {WSAENOTCONN,       "Socket is not connected"},
      {WSAESHUTDOWN,      "Can't send after socket shutdown"},
      {WSAETOOMANYREFS,   "Too many references, can't splice"},
      {WSAETIMEDOUT,      "Connection timed out"},
      {WSAECONNREFUSED,   "Connection refused"},
      {WSAELOOP,          "Too many levels of symbolic links"},
      {WSAENAMETOOLONG,   "File name too long"},
      {WSAEHOSTDOWN,      "Host is down"},
      {WSAEHOSTUNREACH,   "No Route to Host"},
      {WSAENOTEMPTY,      "Directory not empty"},
      {WSAEPROCLIM,       "Too many processes"},
      {WSAEUSERS,         "Too many users"},
      {WSAEDQUOT,         "Disc Quota Exceeded"},
      {WSAESTALE,         "Stale NFS file handle"},
      {WSAEREMOTE,        "Too many levels of remote in path"},
      {WSASYSNOTREADY,    "Network SubSystem is unavailable"},
      {WSAVERNOTSUPPORTED,"WINSOCK DLL Version out of range"},
      {WSANOTINITIALISED, "Successful WSASTARTUP not yet performed"},
      {WSAHOST_NOT_FOUND, "Host not found"},
      {WSATRY_AGAIN,      "Non-Authoritative Host not found"},
      {WSANO_RECOVERY,    "Non-Recoverable errors: FORMERR, REFUSED, NOTIMP"},
      {WSANO_DATA,        "Valid name, no data record of requested"},
      {WSABASEERR,        ""}
      };
  int i;

  i = 0;
  while ((ErrorArray[i].ErrorCode != ErrorCode) &&
         (*ErrorArray[i].ErrorText != '\0')) i++;
  sprintf(Out,"error %lu: %s",ErrorCode,ErrorArray[i].ErrorText);
  }




/**** Communication *********************************************************/




/* Receive a single line from a socket. If the incoming data is
   more than the size of the buffer then data is ignored. Return
   YES if error, NO if allright. */
int ReceiveLine(SOCKET Socket, char *Line, int Width) {
  int Here;
  int Status;
  char c1;

  Here = 0;
  while (1) {
    Status = recv(Socket,&c1,1,0);           /* Receive 1 character. */
    if (Status == 0) break;                /* Leave if no more data. */
    if (Status == SOCKET_ERROR) break;            /* Leave if error. */
    if (c1 == '\r') continue;                          /* Ignore CR. */
    if (c1 == '\0') continue;                        /* Ignore Null. */
    if (c1 == '\n') break;                        /* Leave after LF. */
    if (Here < Width - 1) Line[Here++] = c1;        /* Save in Line. */
    }
  Line[Here] = '\0';
  if (Console == YES) fprintf(stdout,"<<< %s\n",Line);
  if (Status == SOCKET_ERROR) return(YES);
  return(NO);
  }




/* Return a message to the remote. */
int SendReply(SOCKET Socket, char *Message) {
  int Error;

  if (Console == YES) fprintf(stdout,">>> %s\n",Message);
  Error = send(Socket,Message,strlen(Message),0);
  if (Error == SOCKET_ERROR) return(YES);
  Error = send(Socket,"\r\n",2,0);
  if (Error == SOCKET_ERROR) return(YES);
  return(NO);
  }




/**** Program functions *****************************************************/




/* Walk through all items in the configuration fileand return YES
   if a line is found that matches the password and mask. */
int FindSyncItem(
    char *Challenge,
    char *Password,
    char *Mask) {
  FILE *Fin;
  char Line[BUFSIZ];
  char *Here;
  char Key[BUFSIZ];
  int Result;
  char s1[BUFSIZ];
  char s2[BUFSIZ];

  Fin = fopen(CfgPath,"r");
  if (Fin == NULL) return(NO);
  Result = NO;
  while (fgets(Line,BUFSIZ,Fin) != NULL) {
    if (*Line == '#') continue;
    Here = AcceptWord(Line,Key,BUFSIZ);
    if ((stricmp(Key,"access") != 0) && (stricmp(Key,"sync") != 0)) continue;
    Here = AcceptWord(Here,s1,BUFSIZ);
    PasswordEncode(Challenge,s1,s2);
    if (strcmp(Password,s2) != 0) continue;
    striptw(s1,Here);
    FixupPath(s1);
    if (MatchMask(Mask,s1) == NO) continue;
    Result = YES;
    break;
    }
  fclose(Fin);
  return(Result);
  }




/* Dump a list of files. Walk through all files in the root
   directory, and iterate for subdirectories. */
int ListFiles(SOCKET Socket, char *InPath) {
  char Path[BUFSIZ];
  char SearchPath[BUFSIZ];
  char FilePath[BUFSIZ];
  long dirp;
  struct _finddata_t dp;
  struct tm *DateTm;
  int Error;
  char s1[BUFSIZ];
  char *p1;

  /* Fixup the input path. We need a searchpath with a trailing '*'
     and a path that ends in '/'. */
  strcpy(Path,InPath);
  p1 = strchr(Path,'*');
  if (p1 != NULL) {
      strcpy(SearchPath,Path);
      *p1 = '\0';
    } else {
      sprintf(SearchPath,"%s*",Path);
      p1 = strchr(Path,'\0');
      }
  while ((p1 != Path) && ((*p1 == '\0') || (strchr(DIRSEP,*p1) == NULL))) p1--;
  if (strchr(DIRSEP,*p1) != NULL) p1++;
  *p1 = '\0';

  dirp = _findfirst(SearchPath,&dp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -