#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <wininet.h>
#include <winsock2.h>
#else
#include <unistd.h>
#endif

#define ifn(x) if(x==NULL)exit(1);

long uptime();
char* hostname();
char* getos();
void geturl(long, char*, char*);
void onreboot(void);
char* escape(char*);
void die(char*);

int main(int argc, char** argv)
{
   onreboot();

   while(1)
   {
      long uptim = uptime();
      char* name = escape(hostname());
      char* os = escape(getos());
      geturl(uptim, name, os);

      free(name);
      free(os);

      #ifdef _WIN32
      Sleep(60 * 30 * 1000);
      #else
      sleep(60 * 30 * 1000);
      #endif
   }
}

char* escape(char* str)
{
   char* output = (char*)calloc((strlen(str) * 3) + 1, sizeof(char));
   ifn(output)

   int i = 0;
   for(; i < strlen(str); i++)
   {
      if(str[i] == ' ') strcat(output, "%20");
      else if(str[i] == '@') strcat(output, "%40");
      else if(str[i] == ';') strcat(output, "%3B");
      else if(str[i] == '/') strcat(output, "%2F");
      else if(str[i] == '?') strcat(output, "%3F");
      else if(str[i] == ':') strcat(output, "%3A");
      else if(str[i] == '&') strcat(output, "%26");
      else if(str[i] == '=') strcat(output, "%3D");
      else if(str[i] == '+') strcat(output, "%2B");
      else if(str[i] == '$') strcat(output, "%24");
      else if(str[i] == ',') strcat(output, "%2C");
      else output[strlen(output)] = str[i];
   }

   free(str);
   return output;
}

void die(char* error)
{
   printf("Error: %s", error);
   exit(1);
}

#ifdef _WIN32
long uptime()
{
   long uptime = (long)GetTickCount();

   return uptime;
}

void geturl(long uptime, char* name, char* os)
{
   char* input = (char*)malloc(sizeof(char) * (100 + strlen(name) + strlen(os) + 1));
   ifn(input)

   sprintf(input, "http://www.bloople.net/uptime/ut.php?t=%li&hn=%s&os=%s", uptime, name, os);

   HINTERNET con = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
   con = InternetOpenUrl(con, (LPCSTR)input, NULL, 0, 0, 0);
   InternetCloseHandle(con);
}

char* hostname()
{
   WSADATA data;
   int error = WSAStartup(MAKEWORD(2, 0), &data);
   if(error != 0)exit(0);

   char* hn = (char*)malloc(sizeof(char) * (100 + 1));
   ifn(hn)

   gethostname(hn, 100);

   WSACleanup();

   return hn;
}

void onreboot(void)
{
   TCHAR path[MAX_PATH];
   GetModuleFileName(NULL, path, MAX_PATH);

   HKEY key;
   RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &key);
   RegSetValueEx(key, "uptime", 0, REG_SZ, path, strlen(path) + 1);
   RegCloseKey(key);
}

char* getos()
{
   char* output = (char*)malloc(sizeof(char) * (30 + 1));
   ifn(output)

   OSVERSIONINFO ver;
   ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   GetVersionEx(&ver);

   if(ver.dwMajorVersion == 4 && ver.dwMinorVersion == 0) strcpy(output, "^Windows 95/NT 4.0");
   else if(ver.dwMajorVersion == 4 && ver.dwMinorVersion == 1) strcpy(output, "^Windows 98");
   else if(ver.dwMajorVersion == 4 && ver.dwMinorVersion == 9) strcpy(output, "^Windows ME");
   else if(ver.dwMajorVersion == 5 && ver.dwMinorVersion == 0) strcpy(output, "^Windows 2000");
   else if(ver.dwMajorVersion == 5 && ver.dwMinorVersion == 1) strcpy(output, "^Windows XP");
   else if(ver.dwMajorVersion == 5 && ver.dwMinorVersion == 2) strcpy(output, "^Windows Server 2003");
   else if(ver.dwMajorVersion == 6 && ver.dwMinorVersion == 0) strcpy(output, "^Windows Vista/Windows \"Longhorn\" Server");
   else sprintf(output, "^Windows version %i.%i", ver.dwMajorVersion, ver.dwMinorVersion);

   return output;
}
#elif HAVE_PROC_UPTIME
void geturl(long uptime, char* name, char* os)
{
   char* input = (char*)malloc(sizeof(char) * (100 + strlen(name) + strlen(os) + 1));
   ifn(input)

   sprintf(input, "wget -q -O- \"http://www.bloople.net/uptime/ut.php?t=%li&hn=%s&os=%s\" > /dev/null", uptime, name, os);
   system(input);

   free(input);
}

long uptime()
{
   FILE* handle = fopen("/proc/uptime", "r");
   ifn(handle)

   char* timestr = (char*)malloc(sizeof(char) * (80 + 1));
   ifn(timestr)

   char* temp = fgets(timestr, 81, handle);
   ifn(temp)

   fclose(handle);

   long uptime = (long)(atof(timestr) * 1000.0);

   free(timestr);

   return uptime;
}

char* hostname()
{
   char* hn = (char*)malloc(sizeof(char) * (100 + 1));
   ifn(hn)

   gethostname(hn, 100);

   return hn;
}

void onreboot(void)
{
   char* path = (char*)malloc(sizeof(char) * (255 + 1));
   if(path == NULL) return;

   int error = readlink("/proc/self/exe", path, 255);
   if(error == -1) return;

   printf("Please add the line \"%s &\" to /etc/rc.local for up to start at reboot.\n", path);
   /*error = symlink(path, "/root/up");
   if(error < 0)
   {
      int error = unlink("/root/up");
   }

   FILE* handle = fopen("/etc/rc.d/rc.local", "a");
   if(handle == NULL) return;

   error = fputs("/root/up", handle);
   if(error == EOF) return;

   error = fputs(" &", handle);
   if(error == EOF) return;

 

   error = fputc('\n', handle);
   if(error == EOF) return;

   fclose(handle);*/
}

char* getos()
{
   FILE* handle = fopen("/proc/version", "r");
   ifn(handle)

   char* osstr = (char*)malloc(sizeof(char) * (100 + 1));
   ifn(osstr)

   char* temp = fgets(osstr, 101, handle);
   ifn(temp)

   fclose(handle);

   return osstr;
}
#else
void geturl(long uptime, char* name, char* os)
{
   char* input = (char*)malloc(sizeof(char) * (100 + strlen(name) + strlen(os) + 1));
   ifn(input)

   sprintf(input, "wget -q -O- \"http://www.bloople.net/uptime/ut.php?t=%li&hn=%s&os=%s\" > /dev/null", uptime, name, os);
   system(input);

   free(input);
}

long uptime()
{
   static int[2] req = {CTL_KERN, KERN_BOOTTIME};
   struct timeval realUptime;
   size_t uptimelen = sizeof(realUptime);

   int error = sysctl(req, 2, &realUptime, &uptimelen, NULL, 0);
   if(error < 0) exit(1);

   return time(NULL) - realUptime.tv_sec;
}

char* hostname()
{
   char* hn = (char*)malloc(sizeof(char) * (100 + 1));
   ifn(hn)

   gethostname(hn, 100);

   return hn;
}

void onreboot(void)
{
   char* path = (char*)malloc(sizeof(char) * (255 + 1));
   if(path == NULL) return;

   int error = readlink("/proc/self/exe", path, 255);
   if(error == -1) return;

   printf("Please add the line \"%s &\" to /etc/rc.local for up to start at reboot.\n", path);
   /*error = symlink(path, "/root/up");
   if(error < 0)
   {
      int error = unlink("/root/up");
   }

   FILE* handle = fopen("/etc/rc.d/rc.local", "a");
   if(handle == NULL) return;

   error = fputs("/root/up", handle);
   if(error == EOF) return;

   error = fputs(" &", handle);
   if(error == EOF) return;

 

   error = fputc('\n', handle);
   if(error == EOF) return;

   fclose(handle);*/
}

char* getos()
{
   FILE* handle = fopen("/proc/version", "r");
   ifn(handle)

   char* osstr = (char*)malloc(sizeof(char) * (100 + 1));
   ifn(osstr)

   char* temp = fgets(osstr, 101, handle);
   ifn(temp)

   fclose(handle);

   return osstr;
}
#endif
