diff options
Diffstat (limited to 'FortuneAwayMsg/fortune.c')
-rw-r--r-- | FortuneAwayMsg/fortune.c | 246 |
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; +} |