summaryrefslogtreecommitdiff
path: root/FortuneAwayMsg/fortune.c
diff options
context:
space:
mode:
Diffstat (limited to 'FortuneAwayMsg/fortune.c')
-rw-r--r--FortuneAwayMsg/fortune.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/FortuneAwayMsg/fortune.c b/FortuneAwayMsg/fortune.c
new file mode 100644
index 0000000..6bfebeb
--- /dev/null
+++ b/FortuneAwayMsg/fortune.c
@@ -0,0 +1,246 @@
+/*
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+// System includes
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <windows.h>
+
+// Miranda Includes
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_utils.h>
+
+// Fortune include
+#include "fortune.h"
+#include "m_fortunemsg.h"
+
+void bigEndian2littleEndian(void *, size_t);
+unsigned int random(unsigned int);
+size_t readFortuneItem(char *, unsigned int, FILE *, FILE *, unsigned char, unsigned int);
+void normalizeMsg(char *);
+void trimFortune(char *);
+void addCRBeforeLF(char *, unsigned int);
+
+#define isSpace(a) (a == ' ' || a == '\t' || a == '\r' || a == '\n')
+
+BOOL readFortune(const char *dbSetting, char *messageBuf, unsigned int maxFortuneMsg)
+{
+ DBVARIANT dbv;
+ char datFilename[MAX_PATH+1], fortuneFilename[MAX_PATH+1];
+ FILE *fDatfile, *fFortunefile;
+ DATFILEHEADER datHeader;
+ int rCountdown;
+
+ if (DBGetContactSetting(NULL, MODULE_NAME, dbSetting, &dbv))
+ return FALSE;
+ makeAbsolute(datFilename, dbv.pszVal);
+ DBFreeVariant(&dbv);
+
+ if (strlen(datFilename) < 5)
+ return FALSE;
+ if (!(fDatfile=fopen(datFilename, "rb")))
+ return FALSE;
+ if (fread(&datHeader, sizeof(DATFILEHEADER), 1, fDatfile) < 1)
+ return FALSE;
+ bigEndian2littleEndian(&(datHeader.dat_version), sizeof(unsigned int));
+ bigEndian2littleEndian(&(datHeader.dat_numstr), sizeof(unsigned int));
+ bigEndian2littleEndian(&(datHeader.dat_longlen), sizeof(unsigned int));
+ bigEndian2littleEndian(&(datHeader.dat_shortlen), sizeof(unsigned int));
+ bigEndian2littleEndian(&(datHeader.dat_flags), sizeof(unsigned int));
+
+ if (datHeader.dat_shortlen > maxFortuneMsg)
+ return FALSE;
+
+ strcpy(fortuneFilename, datFilename);
+ fortuneFilename[strlen(fortuneFilename) - 4] = '\0';
+
+ if (!(fFortunefile=fopen(fortuneFilename, "rt")))
+ return FALSE;
+
+ for(rCountdown=MAX_RETRIES; rCountdown && readFortuneItem(messageBuf, random(datHeader.dat_numstr), fDatfile, fFortunefile, datHeader.DELIM, maxFortuneMsg) == -1; rCountdown--);
+
+ fclose(fDatfile);
+ fclose(fFortunefile);
+ return !!rCountdown;
+}
+
+void bigEndian2littleEndian(void *convField, size_t fieldSize)
+{
+ size_t i;
+ char aux[128];
+
+ memcpy(aux, convField, fieldSize);
+ for (i=0; i < (fieldSize / 2); i++) {
+ char aux2;
+ int j = fieldSize - i - 1;
+
+ aux2 = aux[i];
+ aux[i] = aux[j];
+ aux[j] = aux2;
+ }
+ memcpy(convField, aux, fieldSize);
+}
+
+unsigned int random(unsigned int maxNumber)
+{
+ static time_t seed = 0;
+
+ if (seed == 0) {
+ (void)time(&seed);
+ srand((unsigned int)seed);
+ }
+
+ return (unsigned int)(rand() % maxNumber);
+}
+
+size_t readFortuneItem(char *fortuneMsg, unsigned int nroItem, FILE *fDatfile, FILE *fFortunefile, unsigned char delimiter, unsigned int maxFortuneMsg)
+{
+ size_t countBytes = 0;
+ f_offset fortuneOffset;
+ char buffer[2*FORTUNE_BUFSIZE], messageBuf[2*FORTUNE_BUFSIZE];
+
+ messageBuf[0] = fortuneMsg[0] = '\0';
+ if (fseek(fDatfile, (long)(sizeof(DATFILEHEADER) + nroItem * sizeof(f_offset)), SEEK_SET))
+ return 0;
+ if (fread(&fortuneOffset, sizeof(f_offset), 1, fDatfile) < 1)
+ return 0;
+ bigEndian2littleEndian(&fortuneOffset, sizeof(f_offset));
+
+ if (fseek(fFortunefile, (long)fortuneOffset, SEEK_SET))
+ return 0;
+ while(fgets(buffer, 2*FORTUNE_BUFSIZE, fFortunefile) != NULL && !(buffer[0] == delimiter && buffer[1] == '\n')) {
+ if ((countBytes += strlen(buffer)) > (2*FORTUNE_BUFSIZE-1))
+ return -1;
+ strcat(messageBuf, buffer);
+ }
+
+ if (DBGetContactSettingByte(NULL, MODULE_NAME, "OneLine", 0))
+ normalizeMsg(messageBuf);
+ else {
+ trimFortune(messageBuf);
+ if (!DBGetContactSettingByte(NULL, MODULE_NAME, "RemoveCR", 0))
+ addCRBeforeLF(messageBuf, maxFortuneMsg);
+ }
+
+ if ((countBytes = strlen(messageBuf)) > maxFortuneMsg)
+ return -1;
+ strcpy(fortuneMsg, messageBuf);
+ return countBytes;
+}
+
+void normalizeMsg(char *fortuneMsg)
+{
+ char buffer[2*FORTUNE_BUFSIZE], *str;
+
+ strcpy(buffer, fortuneMsg);
+
+ if (!(str=strtok(buffer, " \t\r\n")))
+ fortuneMsg[0] = '\0';
+ else {
+ strcpy(fortuneMsg, str);
+ while(str = strtok(NULL, " \t\r\n")) {
+ strcat(fortuneMsg, " ");
+ strcat(fortuneMsg, str);
+ }
+ }
+}
+
+void trimFortune(char *fortuneMsg)
+{
+ int i;
+
+ for (i=strlen(fortuneMsg)-1; i >= 0 && isSpace(fortuneMsg[i]); i--)
+ fortuneMsg[i] = '\0';
+}
+
+void addCRBeforeLF(char *fortuneMsg, unsigned int maxFortuneMsg)
+{
+ int i, j, empty;
+ char buffer[2*FORTUNE_BUFSIZE];
+
+ if ((empty = maxFortuneMsg - strlen(fortuneMsg)) < 0) return;
+
+ strcpy(buffer, fortuneMsg);
+
+ for (i=j=0; buffer[i]; i++) {
+ if (empty && buffer[i] == '\n') {
+ empty--;
+ fortuneMsg[j++] = '\r';
+ }
+ fortuneMsg[j++] = buffer[i];
+ }
+ fortuneMsg[j] = '\0';
+}
+
+BOOL selectRandomFile(char *datFilename)
+{
+ DBVARIANT dbv;
+ char szDir[MAX_PATH+1], szMask[MAX_PATH+1];
+ WIN32_FIND_DATA FileData;
+ HANDLE hSearch;
+ int count = 0;
+
+ datFilename[0] = '\0';
+
+ if (DBGetContactSetting(NULL, MODULE_NAME, "FortuneDir", &dbv)) return FALSE;
+
+ strcpy(szDir, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ makeAbsolute(szMask, szDir);
+ strcat(szMask, "\\*.dat");
+
+ if ((hSearch=FindFirstFile(szMask, &FileData)) == INVALID_HANDLE_VALUE) return FALSE;
+ do {
+ count++;
+ } while (FindNextFile(hSearch, &FileData));
+
+ count = random(count);
+
+ if ((hSearch=FindFirstFile(szMask, &FileData)) == INVALID_HANDLE_VALUE) return FALSE;
+ do {
+ if(count-- == 0) {
+ strcpy(datFilename, szDir);
+ strcat(datFilename, "\\");
+ strcat(datFilename, FileData.cFileName);
+ return TRUE;
+ }
+ } while (FindNextFile(hSearch, &FileData));
+
+ return FALSE;
+}
+
+char *makeRelative(char *returnPath, const char *path)
+{
+ strcpy(returnPath, path);
+ if (ServiceExists(MS_UTILS_PATHTORELATIVE))
+ CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)path, (LPARAM)returnPath);
+
+ return returnPath;
+}
+
+char *makeAbsolute(char *returnPath, const char *path)
+{
+ strcpy(returnPath, path);
+ if (ServiceExists(MS_UTILS_PATHTOABSOLUTE))
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)path, (LPARAM)returnPath);
+
+ return returnPath;
+}