int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf) { uint32_t l; uint32_t realSize; const uint8_t *p; l=GWEN_Buffer_GetUsedBytes(buf); if (l<11) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too few bytes"); return GWEN_ERROR_INVALID; } p=(const uint8_t*)GWEN_Buffer_GetStart(buf); if (*p!=0x60) { DBG_ERROR(GWEN_LOGDOMAIN, "First byte is not a 0x60"); return GWEN_ERROR_BAD_DATA; } p++; l=0; while(*p==0x00) { l++; p++; } if (*p!=0x01) { /*DBG_ERROR(GWEN_LOGDOMAIN, "First byte after padding is not a 0x01");*/ return GWEN_ERROR_BAD_DATA; } realSize=GWEN_Buffer_GetUsedBytes(buf)-11-l; GWEN_Buffer_Crop(buf, 10+l, realSize); return 0; }
int GWEN_Padd__UnpaddWithPkcs1Bt1Or2(GWEN_BUFFER *buf) { char *p; uint32_t len; uint32_t paddBytes; assert(buf); len=GWEN_Buffer_GetUsedBytes(buf); assert(len); p=GWEN_Buffer_GetStart(buf); if (*p==0) { p++; len--; } if (len<11) { DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes left (%d)", len); return GWEN_ERROR_INVALID; } if (*p!=0x01 && *p!=0x02) { DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported block type %02x", *p); return GWEN_ERROR_INVALID; } p++; len--; /* skip padding bytes */ paddBytes=0; while(*p!=0x00 && len) { p++; len--; paddBytes++; } if (*p!=0x00) { DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding"); return GWEN_ERROR_INVALID; } p++; len--; if (paddBytes<8) { /* at least 8 padding bytes are needed */ DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding (too few padding bytes)"); return GWEN_ERROR_INVALID; } GWEN_Buffer_Crop(buf, GWEN_Buffer_GetUsedBytes(buf)-len, len); return 0; }
int GWEN_Directory_GetFileEntriesWithType(const char *folder, GWEN_STRINGLIST *sl, const char *mask) { GWEN_DIRECTORY *d; int rv; char buffer[256]; GWEN_BUFFER *pbuf; uint32_t pos; d=GWEN_Directory_new(); rv=GWEN_Directory_Open(d, folder); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_Directory_free(d); return rv; } pbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(pbuf, folder); GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S); pos=GWEN_Buffer_GetPos(pbuf); while(0==GWEN_Directory_Read(d, buffer+1, sizeof(buffer)-2)) { if (strcmp(buffer, ".")!=0 && strcmp(buffer, "..")!=0 && (mask==NULL || GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) { struct stat st; GWEN_Buffer_AppendString(pbuf, buffer+1); if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) { if (S_ISREG(st.st_mode)) buffer[0]='f'; else if (S_ISDIR(st.st_mode)) buffer[0]='d'; else buffer[0]='?'; GWEN_StringList_AppendString(sl, buffer, 0, 1); } GWEN_Buffer_Crop(pbuf, 0, pos); } } GWEN_Directory_Close(d); GWEN_Directory_free(d); return 0; }
int GWEN_Padd_UnpaddWithAnsiX9_23FromMultipleOf(GWEN_BUFFER *src, int y) { const char *p; unsigned int lastpos; unsigned char paddLength; lastpos=GWEN_Buffer_GetUsedBytes(src); if (lastpos<y) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } lastpos--; p=GWEN_Buffer_GetStart(src)+lastpos; paddLength=*p; if (paddLength<1 || paddLength>y) { DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding (%d bytes ?)", paddLength); return -1; } GWEN_Buffer_Crop(src, 0, GWEN_Buffer_GetUsedBytes(src)-paddLength); GWEN_Buffer_SetPos(src, lastpos-paddLength); return 0; }
static int addToList(const char *fname, int recursive, GWEN_STRINGLIST *sl) { struct stat st; int rv; /* stat file to be added */ #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED rv=lstat(fname, &st); #else rv=stat(fname, &st); #endif if (rv) { DBG_ERROR(GSA_LOGDOMAIN, "stat(%s): %d (%s)", fname, errno, strerror(errno)); fprintf(stderr, "Ignoring file \"%s\"\n", fname); } else { /* always append this entry */ GWEN_StringList_AppendString(sl, fname, 0, 1); if (recursive && S_ISDIR(st.st_mode)) { GWEN_STRINGLIST *sll; GWEN_STRINGLISTENTRY *se; GWEN_DIRECTORY *d; int rv; char buffer[256]; GWEN_BUFFER *tbuf; uint32_t pos; /* add entries */ sll=GWEN_StringList_new(); d=GWEN_Directory_new(); rv=GWEN_Directory_Open(d, fname); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_Directory_free(d); GWEN_StringList_free(sll); return rv; } while(0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) { if (strcmp(buffer, ".")!=0 && strcmp(buffer, "..")!=0) GWEN_StringList_AppendString(sll, buffer, 0, 1); } GWEN_Directory_Close(d); GWEN_Directory_free(d); /* recurse */ tbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(tbuf, fname); GWEN_Buffer_AppendString(tbuf, GWEN_DIR_SEPARATOR_S); pos=GWEN_Buffer_GetPos(tbuf); se=GWEN_StringList_FirstEntry(sll); while(se) { const char *s; s=GWEN_StringListEntry_Data(se); if (s && *s) { GWEN_Buffer_AppendString(tbuf, s); rv=addToList(GWEN_Buffer_GetStart(tbuf), recursive, sl); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(tbuf); GWEN_StringList_free(sll); return rv; } } GWEN_Buffer_Crop(tbuf, 0, pos); se=GWEN_StringListEntry_Next(se); } /* while se */ GWEN_Buffer_free(tbuf); GWEN_StringList_free(sll); } /* if dir and recursive */ } /* if stat was ok */ return 0; }
int LC_Client_InitCommon() { if (lc_client__initcounter==0) { int rv; GWEN_STRINGLIST *paths; rv=GWEN_Init(); if (rv) { DBG_ERROR_ERR(LC_LOGDOMAIN, rv); return rv; } if (!GWEN_Logger_IsOpen(LC_LOGDOMAIN)) { const char *s; /* only set our logger if it not already has been */ GWEN_Logger_Open(LC_LOGDOMAIN, "chipcard3-client", 0, GWEN_LoggerType_Console, GWEN_LoggerFacility_User); GWEN_Logger_SetLevel(LC_LOGDOMAIN, GWEN_LoggerLevel_Warning); s=getenv("LC_LOGLEVEL"); if (s) { GWEN_LOGGER_LEVEL ll; ll=GWEN_Logger_Name2Level(s); if (ll!=GWEN_LoggerLevel_Unknown) { GWEN_Logger_SetLevel(LC_LOGDOMAIN, ll); DBG_WARN(LC_LOGDOMAIN, "Overriding loglevel for Libchipcard-Client with \"%s\"", s); } else { DBG_ERROR(0, "Unknown loglevel \"%s\"", s); } } else { GWEN_Logger_SetLevel(LC_LOGDOMAIN, GWEN_LoggerLevel_Warning); } } /* define sysconf path */ GWEN_PathManager_DefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); #if defined(OS_WIN32) || defined(ENABLE_LOCAL_INSTALL) /* add folder relative to EXE */ GWEN_PathManager_AddRelPath(LCC_PM_LIBNAME, LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR, LC_CLIENT_CONFIG_DIR, GWEN_PathManager_RelModeExe); #else /* add absolute folder */ GWEN_PathManager_AddPath(LCC_PM_LIBNAME, LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR, LC_CLIENT_CONFIG_DIR); #endif /* define data path */ GWEN_PathManager_DefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); #if defined(OS_WIN32) || defined(ENABLE_LOCAL_INSTALL) /* add folder relative to EXE */ GWEN_PathManager_AddRelPath(LCC_PM_LIBNAME, LCC_PM_LIBNAME, LCC_PM_DATADIR, LC_CLIENT_XML_DIR, GWEN_PathManager_RelModeExe); #else /* add absolute folder */ GWEN_PathManager_AddPath(LCC_PM_LIBNAME, LCC_PM_LIBNAME, LCC_PM_DATADIR, LC_CLIENT_XML_DIR); #endif /* load configuration file */ #if 0 paths=GWEN_PathManager_GetPaths(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); if (paths) { GWEN_DB_NODE *db; GWEN_BUFFER *fbuf; db=GWEN_DB_Group_new("config"); fbuf=GWEN_Buffer_new(0, 256, 0, 1); rv=GWEN_Directory_FindFileInPaths(paths, LC_CLIENT_CONFIG_FILE, fbuf); if (rv) { DBG_INFO(LC_LOGDOMAIN, "Trying config file with suffix \".default\""); rv=GWEN_Directory_FindFileInPaths(paths, LC_CLIENT_CONFIG_FILE".default", fbuf); } GWEN_StringList_free(paths); if (rv) { DBG_WARN(LC_LOGDOMAIN, "No configuration file found, using defaults"); } else { DBG_INFO(LC_LOGDOMAIN, "Reading configuration file \"%s\"", GWEN_Buffer_GetStart(fbuf)); rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(fbuf), GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_CREATE_GROUP); if (rv<0) { DBG_ERROR(LC_LOGDOMAIN, "Error in configuration file \"%s\" (%d)", GWEN_Buffer_GetStart(fbuf), rv); GWEN_Buffer_free(fbuf); /* undo all init stuff so far */ GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); return rv; } } GWEN_Buffer_free(fbuf); lc_client__config=db; } else { DBG_ERROR(LC_LOGDOMAIN, "Internal error: Paths not found"); return GWEN_ERROR_INTERNAL; } #else lc_client__config=GWEN_DB_Group_new("config"); #endif /* load XML files */ paths=GWEN_PathManager_GetPaths(LCC_PM_LIBNAME, LCC_PM_DATADIR); if (paths) { GWEN_XMLNODE *n; GWEN_DB_NODE *db; GWEN_BUFFER *fbuf; uint32_t bpos; fbuf=GWEN_Buffer_new(0, 256, 0, 1); rv=GWEN_Directory_FindPathForFile(paths, "cards/README", fbuf); GWEN_StringList_free(paths); if (rv) { DBG_ERROR(LC_LOGDOMAIN, "Data files not found (%d)", rv); /* undo all init stuff so far */ GWEN_Buffer_free(fbuf); GWEN_DB_Group_free(lc_client__config); lc_client__config=NULL; GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); return rv; } /* load card files */ n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "cards"); if (LC_Client_ReadXmlFiles(n, GWEN_Buffer_GetStart(fbuf), "cards", "card")) { DBG_ERROR(LC_LOGDOMAIN, "Could not read card files"); GWEN_XMLNode_free(n); /* undo all init stuff so far */ GWEN_Buffer_free(fbuf); GWEN_DB_Group_free(lc_client__config); lc_client__config=NULL; GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); return GWEN_ERROR_GENERIC; } lc_client__card_nodes=n; /* load app files */ n=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "apps"); if (LC_Client_ReadXmlFiles(n, GWEN_Buffer_GetStart(fbuf), "apps", "app")) { DBG_ERROR(LC_LOGDOMAIN, "Could not read app files"); GWEN_XMLNode_free(n); /* undo all init stuff so far */ GWEN_XMLNode_free(lc_client__card_nodes); lc_client__card_nodes=NULL; GWEN_Buffer_free(fbuf); GWEN_DB_Group_free(lc_client__config); lc_client__config=NULL; GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); return GWEN_ERROR_GENERIC; } lc_client__app_nodes=n; /*GWEN_XMLNode_WriteFile(n, "/tmp/apps", GWEN_XML_FLAGS_DEFAULT);*/ /* load driver files (if any) */ bpos=GWEN_Buffer_GetPos(fbuf); GWEN_Buffer_AppendString(fbuf, DIRSEP "drivers"); db=GWEN_DB_Group_new("drivers"); rv=LC_DriverInfo_ReadDrivers(GWEN_Buffer_GetStart(fbuf), db, 0, 1); if (rv) { DBG_INFO(LC_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(db); /* undo all init stuff so far */ GWEN_XMLNode_free(lc_client__app_nodes); lc_client__app_nodes=NULL; GWEN_XMLNode_free(lc_client__card_nodes); lc_client__card_nodes=NULL; GWEN_Buffer_free(fbuf); GWEN_DB_Group_free(lc_client__config); lc_client__config=NULL; GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); return rv; } lc_client__driver_db=db; GWEN_Buffer_Crop(fbuf, 0, bpos); /* insert more loading here */ GWEN_Buffer_free(fbuf); } else { DBG_ERROR(LC_LOGDOMAIN, "No data files found."); /* undo all init stuff so far */ GWEN_DB_Group_free(lc_client__config); lc_client__config=NULL; GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_DATADIR); GWEN_PathManager_UndefinePath(LCC_PM_LIBNAME, LCC_PM_SYSCONFDIR); return GWEN_ERROR_GENERIC; } } lc_client__initcounter++; return 0; }
int GWEN_LibLoader_OpenLibraryWithPath(GWEN_LIBLOADER *h, const char *path, const char *name) { GWEN_BUFFER *buffer; unsigned int pos; unsigned int pos2; unsigned int i; int missingSoExt; int missingLibPrefix; int err; assert(h); assert(name); missingSoExt=0; missingLibPrefix=0; buffer=GWEN_Buffer_new(0, 256, 0, 1); if (path) { GWEN_Buffer_AppendString(buffer, path); GWEN_Buffer_AppendByte(buffer, '/'); } /* remember current position */ pos=GWEN_Buffer_GetPos(buffer); /* append name of the library to load */ GWEN_Buffer_AppendString(buffer, name); i=strlen(name); /* check whether we have the ".so" extension */ if ((i<=3) || (strcmp(name+i-3, ".so")!=0)) { /* no SO-extension, add it myself */ missingSoExt=1; } /* check whether we have the "lib" prefix */ if ((i<=3) || (strncmp(name, "lib", 3)!=0)) { /* no SO-extension, add it myself */ missingLibPrefix=1; } /* try to load the library */ err=GWEN_LibLoader_LoadLibrary(h, GWEN_Buffer_GetStart(buffer)); if (!err) { DBG_INFO(GWEN_LOGDOMAIN, "Library \"%s\" loaded", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return 0; } /* could not load, check why */ /*if (GWEN_Error_GetType(err)!= GWEN_Error_FindType(GWEN_LIBLOADER_ERROR_TYPE) || GWEN_Error_GetCode(err)!=GWEN_LIBLOADER_ERROR_NOT_FOUND) { DBG_ERROR_ERR(GWEN_LOGDOMAIN, err); DBG_INFO(GWEN_LOGDOMAIN, "Could not load library \"%s\"", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return err; } */ /* hmm, not found, try some variants */ if (missingSoExt) { /* try again, this time with ".so" appended */ pos2=GWEN_Buffer_GetPos(buffer); GWEN_Buffer_AppendString(buffer, ".so"); err=GWEN_LibLoader_LoadLibrary(h, GWEN_Buffer_GetStart(buffer)); if (!err) { DBG_INFO(GWEN_LOGDOMAIN, "Library \"%s\" loaded", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return 0; } GWEN_Buffer_Crop(buffer, 0, pos2); GWEN_Buffer_SetPos(buffer, pos2); /* could not load, check why */ if (err!=GWEN_ERROR_NOT_FOUND) { DBG_INFO(GWEN_LOGDOMAIN, "Could not load library \"%s\"", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return err; } } if (missingLibPrefix) { GWEN_Buffer_SetPos(buffer, pos); /* insert "lib" */ GWEN_Buffer_InsertString(buffer, "lib"); /* try again */ err=GWEN_LibLoader_LoadLibrary(h, GWEN_Buffer_GetStart(buffer)); if (!err) { DBG_INFO(GWEN_LOGDOMAIN, "Library \"%s\" loaded", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return 0; } /* could not load, check why */ if (err!=GWEN_ERROR_NOT_FOUND) { DBG_INFO(GWEN_LOGDOMAIN, "Could not load library \"%s\"", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return err; } /* try again, this time with ".so" AND "lib" */ if (missingSoExt) { GWEN_Buffer_AppendString(buffer, ".so"); err=GWEN_LibLoader_LoadLibrary(h, GWEN_Buffer_GetStart(buffer)); if (!err) { DBG_INFO(GWEN_LOGDOMAIN, "Library \"%s\" loaded", GWEN_Buffer_GetStart(buffer)); GWEN_Buffer_free(buffer); return 0; } } } DBG_INFO(GWEN_LOGDOMAIN, "Library \"%s\" name (or variants) not found, giving up", name); GWEN_Buffer_free(buffer); return err; }
/* * The original code (in C++) has been written by Fabian Kaiser for OpenHBCI * (file rsakey.cpp). Translated to C by Martin Preuss */ int GWEN_Padd_PaddWithISO9796(GWEN_BUFFER *src) { unsigned char *p; unsigned int l; unsigned int i; unsigned char buffer[GWEN_PADD_ISO9796_KEYSIZE]; unsigned char hash[20]; unsigned char c; p=(unsigned char*)GWEN_Buffer_GetStart(src); l=GWEN_Buffer_GetUsedBytes(src); memmove(hash, p, l); /* src+src+src */ if (GWEN_Buffer_AppendBytes(src, (const char*)hash, l)) { DBG_INFO(GWEN_LOGDOMAIN, "here"); return -1; } if (GWEN_Buffer_AppendBytes(src, (const char*)hash, l)) { DBG_INFO(GWEN_LOGDOMAIN, "here"); return -1; } /* src=src(20,40) */ if (GWEN_Buffer_Crop(src, 20, 40)) { DBG_INFO(GWEN_LOGDOMAIN, "here"); return -1; } memset(buffer, 0, sizeof(buffer)); /* append redundancy */ p=(unsigned char*)GWEN_Buffer_GetStart(src); for (i=0; i<=47; i++) { int j1, j2, j3; j1=1 + sizeof(buffer) - (2*i); j2=40-i; j3=sizeof(buffer) - (2*i); if (j1>=0 && j1<(int)sizeof(buffer) && j2>=0) { buffer[j1]=p[j2]; } if (j3>=0 && j3<(int)sizeof(buffer) && j2>=0) { buffer[j3]=GWEN_Padd_permutate(p[j2]); } } /* for */ /* copy last 16 bytes to the beginning */ memmove(buffer, buffer+(sizeof(buffer)-16), 16); p=buffer; /* finish */ c=p[sizeof(buffer)-1]; c = (c & 15) * 16; c += 6; p[sizeof(buffer)-1]=c; p[0] = p[0] & 127; p[0] = p[0] | 64; p[sizeof(buffer) - 40] = p[sizeof(buffer) - 40] ^ 1; GWEN_Buffer_Reset(src); if (GWEN_Buffer_AppendBytes(src, (const char*)buffer, sizeof(buffer))) { DBG_INFO(GWEN_LOGDOMAIN, "here"); return -1; } return 0; }
int AIO_OfxXmlCtx_CleanupData(GWEN_XML_CONTEXT *ctx, const char *data, GWEN_BUFFER *buf) { const uint8_t *p; uint8_t *dst; uint8_t *src; unsigned int size; unsigned int i; int lastWasBlank; uint8_t *lastBlankPos; uint32_t bStart=0; if (GWEN_Text_UnescapeXmlToBuffer(data, buf)) { DBG_INFO(AQBANKING_LOGDOMAIN, "here"); return GWEN_ERROR_BAD_DATA; } dst=(uint8_t*)GWEN_Buffer_GetStart(buf); src=dst; /* skip leading blanks */ while(*src && (*src<33 || *src>=127)) src++; p=src; bStart=src-((uint8_t*)GWEN_Buffer_GetStart(buf)); size=GWEN_Buffer_GetUsedBytes(buf)-bStart; lastWasBlank=0; lastBlankPos=0; for (i=0; i<size; i++) { uint8_t c; c=*p; /* DISABLED: c>=127 would filter out umlauts... if (c<32 || c>=127)*/ if (c<32) c=32; /* remember next loop whether this char was a blank */ if (c==32) { if (!lastWasBlank) { /* store only one blank */ lastWasBlank=1; lastBlankPos=dst; *(dst++)=c; } } else { lastWasBlank=0; lastBlankPos=0; *(dst++)=c; } p++; } /* remove trailing blanks */ if (lastBlankPos!=0) dst=lastBlankPos; size=dst-(uint8_t*)GWEN_Buffer_GetStart(buf); GWEN_Buffer_Crop(buf, 0, size); return 0; }
int GWEN_Directory_GetMatchingFilesRecursively(const char *folder, GWEN_STRINGLIST *sl, const char *mask) { GWEN_DIRECTORY *d; int rv; char buffer[256]; GWEN_BUFFER *pbuf; uint32_t pos; GWEN_STRINGLIST *folderList; folderList=GWEN_StringList_new(); d=GWEN_Directory_new(); rv=GWEN_Directory_Open(d, folder); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_Directory_free(d); GWEN_StringList_free(folderList); return rv; } pbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(pbuf, folder); GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S); pos=GWEN_Buffer_GetPos(pbuf); while(0==GWEN_Directory_Read(d, buffer, sizeof(buffer)-2)) { if (strcmp(buffer, ".")!=0 && strcmp(buffer, "..")!=0) { struct stat st; GWEN_Buffer_AppendString(pbuf, buffer); if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) { if (S_ISDIR(st.st_mode)) /* add folders to the folder list */ GWEN_StringList_AppendString(folderList, GWEN_Buffer_GetStart(pbuf), 0, 0); else { if (mask==NULL || GWEN_Text_ComparePattern(buffer, mask, 0)!=-1) /* don't check for duplicates here (i.e. last param =0) */ GWEN_StringList_AppendString(sl, GWEN_Buffer_GetStart(pbuf), 0, 0); } } GWEN_Buffer_Crop(pbuf, 0, pos); } } GWEN_Directory_Close(d); GWEN_Directory_free(d); if (GWEN_StringList_Count(folderList)) { GWEN_STRINGLISTENTRY *se; se=GWEN_StringList_FirstEntry(folderList); while(se) { const char *s; s=GWEN_StringListEntry_Data(se); if (s && *s) GWEN_Directory_GetMatchingFilesRecursively(s, sl, mask); se=GWEN_StringListEntry_Next(se); } } GWEN_StringList_free(folderList); GWEN_Buffer_free(pbuf); return 0; }