Click here to Skip to main content
15,894,720 members
Articles / Programming Languages / XML

XMLFoundation

Rate me:
Please Sign up or sign in to vote.
4.82/5 (12 votes)
2 Jul 20029 min read 75.2K   1.4K   34  
Obtaining data marked up in XML creates the need for Application Layer tools to easily and efficiently work with XML data.
// --------------------------------------------------------------------------
//					www.UnitedBusinessTechnologies.com
//			  Copyright (c) 1998 - 2002  All Rights Reserved.
//
// Source in this file is released to the public under the following license:
// --------------------------------------------------------------------------
// This toolkit may be used free of charge for any purpose including corporate
// and academic use.  For profit, and Non-Profit uses are permitted.
//
// This source code and any work derived from this source code must retain 
// this copyright at the top of each source file.
// 
// UBT welcomes any suggestions, improvements or new platform ports.
// email to: XMLFoundation@UnitedBusinessTechnologies.com
// --------------------------------------------------------------------------

#include "DirectoryListing.h"
#include "GString.h"
#include "GException.h"
#include <string.h>			// for: strlen() strpbrk()


#if defined _WIN32
	#include <wtypes.h>		
	// FindFirstFile & FindNextFile
	#if _MSC_VER > 1000
		// If this is an MFC app do not include windows.h
	#else
		#include <windows.h>
	#endif
	#include "Winbase.h"
	#include <sys/stat.h>
	#include  <io.h>
	#include  <direct.h> // for: mkdir
#else
	// linux, Solaris, HPUX, AIX
	#include <unistd.h>
	#include <dirent.h>
	#include <sys/stat.h>
	#include <errno.h>
#endif

#if defined _LINUX 
	// opendir & readdir & closedir
	#include <getopt.h>
	#include <pwd.h>
#elif defined __sun || defined _HPUX
	// opendir & readdir & closedir
	#include <sys/types.h>
#endif


// return the last leaf from a fully qualified path (file or directory)
const char *CDirectoryListing::LastLeaf(const char *pzFullPath, char chSlash/*= 0*/)
{
	static GString strReturnValue;
	strReturnValue = "";
	if (pzFullPath && pzFullPath[0])
	{
		strReturnValue = pzFullPath;
		int nLen = strlen(pzFullPath);
		if (chSlash)
		{
			if (pzFullPath[nLen - 1] == chSlash)
				nLen--;

		}
		else if ( pzFullPath[nLen - 1] == '\\' ||  pzFullPath[nLen - 1] == '/')
		{
			nLen--; // if the input value is "/etc/bin/" start searching behind the last '/'
					// so that the return leaf value is "bin"
		}

		for(int i = nLen-1; i > -1; i-- )
		{
			if (chSlash)
			{
				if (pzFullPath[i] == chSlash)
				{
					strReturnValue = &pzFullPath[i+1];
					break;
				}
			}
			else if (pzFullPath[i] == '\\' || pzFullPath[i] == '/')	
			{
				strReturnValue = &pzFullPath[i+1];
				break;
			}
		}
	}
	return strReturnValue;
}



// given "/usr/bob/file.ext"  create [/usr] and [/usr/bob] if necessary
void CDirectoryListing::CreatePath(const char *pzPathOnlyOrPathAndFileName, int bPathHasFileName)
{
	// cast off the const, we'll modify then restore the string
	char *pzFileAndPath = (char *)pzPathOnlyOrPathAndFileName;

	if (!pzFileAndPath)
	{
		return;
	}
	int nLen = strlen(pzFileAndPath);
	for(int i=0;i<nLen+1;i++)
	{
		if (pzFileAndPath[i] == '\\' || pzFileAndPath[i] == '/' || pzFileAndPath[i] == 0)
		{
			if ( bPathHasFileName && pzFileAndPath[i] == 0)
			{
				// if the path includes a filename, we're done.
				break; 
			}

			char ch = pzFileAndPath[i];
			pzFileAndPath[i] = 0;

			int nAttempts = 0;
RETRY_MKDIR:
			nAttempts++;

#ifdef _WIN32
			int nRslt = mkdir(pzFileAndPath);
#else
			int nRslt = mkdir(pzFileAndPath, 777);
#endif			
			// Mircosoft needs this retry...
			if (nRslt != 0 && nAttempts < 5 && errno == 2)
			{
				goto RETRY_MKDIR;
			}

			pzFileAndPath[i] = ch;
		}
	}
}

// returns 1 if the argument is a directory, 0 if it's a file or a bad path.
int CDirectoryListing::IsDirectory(const char *szDirPath)
{
	struct stat sstruct;
	int result = stat(szDirPath, &sstruct);
	if (result == 0)
	{
#ifdef _WIN32
		if ( (sstruct.st_mode & _S_IFDIR)  )
		{
			return 1;
		}
#else
		if ( S_ISDIR(sstruct.st_mode)  )
		{
			return 1;
		}
#endif
	}
	return 0;
}


void CDirectoryListing::RecurseFolder(const char *pzDir, GStringList *strDirs, GStringList *strFiles)
{
#ifdef _WIN32
	char chSlash = '\\';
#else
	char chSlash = '/';
#endif
	static GString strDot("[dir] .");
	static GString strDotDot("[dir] ..");
	try
	{
		// Sample listing 2 files + 1 directory = "file1.txt*[dir] Temp*file2.txt"
		GString strResults;
		CDirectoryListing dir(pzDir, 2); // directories only
		GStringIterator it(&dir);
		while (it())
		{
			// pzResult will look something like "[dir] SubDir"
			const char *pzResult = it++; 
			if (strDot.Compare(pzResult) != 0 && strDotDot.Compare(pzResult) != 0)
			{
				// pzDir may be "/myPath" to begin with
				GString strFullPath(pzDir);
				if ( strFullPath.GetAt(strFullPath.GetLength() - 1) != '\\' && 
					 strFullPath.GetAt(strFullPath.GetLength() - 1) != '/')
				{
					// pzDir will now end with a slash if it did not already.
					// like "/myPath/" or "c:\myPath\"
					strFullPath += chSlash;
				}

				// add the file name to the complete path we're building
				strFullPath += &pzResult[6]; // skip the "[dir] ", add a string like "SubDir"

				if(strDirs)
				{
					strDirs->AddLast(strFullPath);
				}

				// now add the final slash for a string like this "/myPath/SubDir/"
				strFullPath += chSlash;

				// go down into that directory now.
				RecurseFolder(strFullPath, strDirs, strFiles);
			}
		}

		if(strFiles)
		{
			CDirectoryListing files(pzDir, 1); // files only
			GStringIterator it2(&files);
			while (it2())
			{
				// pzDir may be "/myPath" to begin with
				GString strFullPath(pzDir);
				if ( strFullPath.GetAt(strFullPath.GetLength() - 1) != '\\' && 
					 strFullPath.GetAt(strFullPath.GetLength() - 1) != '/')
				{
					// strFullPath will now end with a slash like "/myPath/" 
					strFullPath += chSlash;
				}


				const char *pzFile = it2++;
				strFullPath += pzFile;
				strFiles->AddLast((const char *)strFullPath);
			}
		}
	}
	catch( GenericException & )
	{
		// ignore the directory we can't access 
		// rErr.GetDescription();
	}
}


void CDirectoryListing::Init(const char *szDirPath, int nMode)
{
	static GString dotdot("..");
	static GString dot(".");
	
	bool bIncludeSubDirs = (nMode == 2 || nMode == 3) ? 1 : 0;
	bool bIncludeFiles = (nMode == 1 || nMode == 3) ? 1 : 0;
	
	
	GString strPathWithTrailingSlash(szDirPath);
	GString strPathWithNoTrailingSlash(szDirPath);

	// if szDirPath ends with a slash
	if ( strPathWithNoTrailingSlash.Right(1) == "/" ||
		 strPathWithNoTrailingSlash.Right(1) == "\\" )
	{
		// if the path is "/" leave it alone
		if (strPathWithNoTrailingSlash.Length() > 1)
			strPathWithNoTrailingSlash = strPathWithNoTrailingSlash.Left(strPathWithNoTrailingSlash.Length() - 1);
	}
	else
	{
#ifdef _WIN32
			strPathWithTrailingSlash += "\\";
#else 
			strPathWithTrailingSlash += "/";
#endif
	}


#ifdef _WIN32
	if( _access( (const char *)strPathWithNoTrailingSlash, 0 ) )
	{
		throw GenericException("GDirectoryListing",0,(const char *)strPathWithNoTrailingSlash, errno);
	}
#else
	if( access( (const char *)strPathWithNoTrailingSlash, F_OK ) )
	{
		throw GenericException("GDirectoryListing",0,(const char *)strPathWithNoTrailingSlash, errno);
	}
#endif
	

#if defined _WIN32

	// FindFirstFile & FindNextFile
	HANDLE hFindFile;
	WIN32_FIND_DATA find;
	BOOL fRet = TRUE;
	GString strSearch( strPathWithTrailingSlash );
	strSearch += "*.*";
	hFindFile = FindFirstFile((const char *)strSearch, &find);
	while (hFindFile != (HANDLE)-1 && fRet == TRUE) 
	{
		GString strTemp( strPathWithTrailingSlash );
		strTemp += find.cFileName;
		struct stat sstruct;

		int result = stat(strTemp, &sstruct);
		if (result == 0)
		{
			if ( !(sstruct.st_mode & _S_IFDIR)  )
			{
				// Add the file
				if (bIncludeFiles)
				{
					AddLast((const char *)find.cFileName);
				}
			}
			else if (bIncludeSubDirs)
			{
				GString strFileName( LastLeaf( (char *)(const char *)strTemp,'\\') );
				if ( ( dotdot.Compare(strFileName) != 0 ) && ( dot.Compare(strFileName) != 0 ))
				{
					GString strFormattedDir;
					strFormattedDir.Format("[dir] %s", LastLeaf( (char *)(const char *)strFileName,'\\') );
					AddLast((const char *)strFormattedDir);
				}
			}

		}

		fRet = FindNextFile(hFindFile, &find);
	}
	FindClose(hFindFile);
#elif defined _LINUX || defined __sun || defined _HPUX

	DIR *d;
	if (!(d = opendir( (const char *)strPathWithTrailingSlash )))
	{
		// 27=Directory [%s] does not exist or cannot be accessed.
		throw GenericException("GDirectoryListing",0,(const char *)strPathWithNoTrailingSlash, errno);
	}

	struct dirent *dstruct;

	while ((dstruct = readdir(d)))
	{
		struct stat sstruct;

		GString strTemp( strPathWithTrailingSlash );
		strTemp += dstruct->d_name;

		int result = stat((const char *)strTemp, &sstruct);
		if (result == 0)
		{
			if ( !S_ISDIR(sstruct.st_mode)  )
			{
				if (bIncludeFiles)
				{
					// Add files
					AddLast(dstruct->d_name);
				}
			}
			else if (bIncludeSubDirs)
			{
				GString strFileName( LastLeaf( (char *)(const char *)strTemp,'/') );
				if ( ( dotdot.Compare(strFileName) != 0 ) && ( dot.Compare(strFileName) != 0 ))
				{
					// Add Directories
					GString strFormattedDir;
					strFormattedDir.Format("[dir] %s", LastLeaf((char *)(const char *)strFileName,'/') );
					AddLast((const char *)strFormattedDir);
				}
			}
		}
	}

	closedir(d);

#endif
}


CDirectoryListing::CDirectoryListing(const char *szPath)
{
	Init(szPath, 1);
}

// nMode = 1 files, 2 dirs, 3 both
CDirectoryListing::CDirectoryListing(const char *szPath, int nMode)
{
	Init(szPath, nMode);
}

CDirectoryListing::~CDirectoryListing()
{
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Founder United Business Technologies
United States United States
http://about.me/brian.aberle
https://www.linkedin.com/in/brianaberle
http://SyrianRue.org/Brian

Comments and Discussions