File List

A. Second Edition
Little tools to publish all my file list as table.
B.The problem
C.The idea of program
D.The major functions

E.Further improvement
กก
F.File listing
#include <windows.h>
#include <TCHAR.h>
#include <stdio.h>


#define MY_MAX_PATH (4*MAX_PATH)

typedef bool (* HandleFileCallBack)(LPTSTR fullName, LPTSTR fileName, void* pUser);

int pathLength = 0;
int counter = 1;
DWORD numberToWrite;
DWORD number = 0;

int genericFind(LPCTSTR dir, HandleFileCallBack handleFileCallBack, LPTSTR filter=NULL, void* pUser=NULL);


LPSTR header="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\">\n<title>My All File List</title> \n<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head> \n <body><p><font color=\"#FF0000\">\n <font color=\"#FF0000\"><font size=\"7\">\nAll File List\n</font></p>\n";

LPCSTR bottom="</table> </body></html>";

LPSTR table="<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\">\n<tr> <th> file index </th>  <th>\n file name \n</th>  </tr>\n";

LPSTR linkPrefix="<tr><td width=20>%d</td>\n <td> <a href=\"http://www.staroceans.net/%s\">";
LPSTR linkPosfix="</a></td></tr>";

bool createListHelper(LPTSTR fullName, LPTSTR fileName, void* pUser)
{
    char buffer[1024];   
    char linkBuffer[256];
    HANDLE hFile = (HANDLE)pUser;
    LPTSTR relativePath = fullName + pathLength;
    LPTSTR src = relativePath;
    PSTR dst = linkBuffer;
    bool bResult = false;
    int i=0;
   
   
    if (*src == _T('\\'))
    {
        //bypass the first "\\";
        src ++;
    }
    do
    {
        if (*src == _T('\\'))
        {           
            *dst = '/';
           
        }
        else
        {
            *dst = *src;
        }
        if (*src == _T('\0'))
        {
            break;
        }
        src ++;
        dst ++;
    }
    while (true);   

    sprintf(buffer, linkPrefix, counter, linkBuffer);
    numberToWrite = strlen(buffer);
    if (WriteFile(hFile, buffer, numberToWrite, &number, NULL)&& numberToWrite==number)
    {
        numberToWrite = _tcslen(fileName)*sizeof(TCHAR);
        if (WriteFile(hFile, fileName, numberToWrite, &number, NULL)&& numberToWrite==number)
        {               
            numberToWrite = strlen(linkPosfix);
            if (WriteFile(hFile, linkPosfix, numberToWrite, &number, NULL)&& numberToWrite==number)
            {
                bResult = true;
            }
        }
    }
    counter ++;
   
    return bResult;
}
   

void createList(LPTSTR path, LPTSTR fileName)
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    if ((hFile = CreateFile(fileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))!= INVALID_HANDLE_VALUE)
    {       
        numberToWrite = strlen(header);
        pathLength = _tcslen(path);
        if (WriteFile(hFile, header, numberToWrite, &number, NULL) && number == numberToWrite)
        {   
            numberToWrite = strlen(table);
            if (WriteFile(hFile, table, numberToWrite, &number, NULL) && number == numberToWrite)
            {   
                genericFind(path, createListHelper, NULL, hFile);
            }
        }
        numberToWrite =strlen(bottom);

        WriteFile(hFile, bottom, numberToWrite, &number, NULL);
   
        CloseHandle(hFile);
    }
}


int genericFind(LPCTSTR dir, HandleFileCallBack handleFileCallBack, LPTSTR filter, void* pUser)
{
    HANDLE handle;
    int nCounter = 0;
    TCHAR curFileName[MY_MAX_PATH];
    TCHAR wildFileName[MY_MAX_PATH];
    LPTSTR strFileName;
   
    WIN32_FIND_DATA ffd;

    if (filter == NULL)
    {
        strFileName = _T("*.*");
    }
    else
    {
        strFileName = filter;
    }


    _sntprintf(wildFileName, MY_MAX_PATH, _T("%s\\%s"), dir, strFileName);
    handle = FindFirstFile(wildFileName, &ffd);
    if (handle==INVALID_HANDLE_VALUE)
    {
        _tprintf(_T("findfirst failed of error code =%d\n"), GetLastError());
        return 0;
    }
    do
    {   
        if (_tcsicmp(ffd.cFileName, _T("."))!=0 && _tcsicmp(ffd.cFileName, _T(".."))!=0)
        {
            _stprintf(curFileName, _T("%s\\%s"), dir, ffd.cFileName);
            if  (GetFileAttributes(curFileName)&FILE_ATTRIBUTE_DIRECTORY)
            {
                // filter my personal folder
                if (_tcsicmp(ffd.cFileName, _T("personal")) !=0)
                {
                    genericFind(curFileName, handleFileCallBack, filter, pUser);
                }
            }
            else
            {                   
                if (!handleFileCallBack(curFileName, ffd.cFileName, pUser))
                {
                    break;
                }
                else
                {
                    nCounter ++;
                }
            }
        }
    }
    while (FindNextFile(handle, &ffd));   
   
    FindClose(handle);
    return nCounter;
}



int _tmain(int argc, LPTSTR* argv)
{
    //I:\MyWeb\diabloforum mylist.htm
    if (argc == 3)
    {   
        createList(argv[1], argv[2]);
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This is the latest version by using boost as there are some nasty thing about language encoding problem with windows
// api. It is said, in windows, you should always use wide-char api and widestring, but in linux, you should almost never
// use wide char. Till now, I don't really understand this but it works.

#include <iostream>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <string>
#include <map>
#include <algorithm>
#include <cstdio>

using namespace std;
using namespace boost::filesystem;

typedef multimap<string, string> StringMap;

string prefix = "http://www.staroceans.net";

string header1="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>My All File List</title>";
string header2="<meta name=\"GENERATOR\" content=\"Microsoft FrontPage 6.0\"></head>  <body><p><font color=\"#FF0000\">";
string header3="<font color=\"#FF0000\"><font size=\"7\">All File List</font></p>";

string comment1="This is a list of all files in this website and to make it easy for searching, the they are sorted by file name"
    " and here is <a href=\"";
string comment2="/myListTool.html\"> the source code </a> of file how it is generated.";

string tableHeader1="<table border=\"1\" cellpadding=\"5\" cellspacing=\"5\" width=\"100%\">";
string tableHeader2="<tr> <th> file index </th>  <th> file name </th>   </tr>";
string bottom="</table></body></html>";

string tableColumn1 = "<tr> <td width=20>";
string tableColumn2 = "</td>  <td> <a href=\"";
string tableColumn3 = "\">";
string tableColumn4 = "</a> </td> </tr>";



string urlEncode(const string& str)
{
    string result;
    for (int i = 0; i < str.size(); i ++)
    {
        if (str[i]>='0' && str[i] <='9' || str[i]>='A' && str[i] <='Z' || str[i] >= 'a' && str[i] <= 'z')
        {
            result+= str[i];
        }
        else
        {
            const unsigned char MASK1 = 0xF0;
            const unsigned char MASK2 = 0x0F;
            unsigned char ch;

            switch (str[i])
            {
            case '-':
            case '_':
            case '.':
            case '!':
            case '~':
            case '*':
            case '\'':
            case '(':
            case ')':
            case '"':
                result += str[i];
                break;
            default:
                ch = (str[i] & MASK1) >> 4;
                result += '%';

                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                ch = str[i] & MASK2;
                if (ch > 9)
                {
                    ch = ch - 10 + 'A';
                }
                else
                {
                    ch = ch + '0';
                }
                result += ch;
                break;
            }
        }
    }
    return result;
}


void doFile(const string& filePath, StringMap& stringMap, const string& prefix)
{
    //cout<<filePath.file_string()<<endl;
    //cout<<filePath.filename()<<endl;
    string str = prefix + "/" + urlEncode(filePath);

    if (stringMap.insert(make_pair<string, string>(filePath, str)) == stringMap.end())
    {
        //cout<<"error"<<endl;
    }
}

void doDir(const path& thePath, StringMap& stringMap, const string& prefix)
{
    directory_iterator it(thePath), dirEnd;
    while (it != dirEnd)
    {
        //cout<< it->filename()<<endl;
        if (is_directory(*it))
        {
            //cout<< it->filename()<<endl;
            // check if it has white space in between.
            string subPrefix = prefix + "/" + urlEncode(it->filename());
            if (it->filename().compare("personal") != 0)
            {
                doDir(*it, stringMap, subPrefix);
            }
        }
        else
        {
            if (is_regular_file(*it))
            {
                //string str = urlEncode(it->filename());
                doFile(it->filename(), stringMap, prefix);
            }
            else
            {
                //cout<<"file is not regular:"<<it->filename()<<endl;
            }
        }
        it ++;
    }


}

struct ShowStringPair
{
    void showString(const string& str) const
    {
        for (int i = 0; i < str.size(); i ++)
        {
            unsigned char ch = str[i];
            cout<<ch;
            cout.flush();
        }
    }

    void operator()(const pair<string, string>& strPair) const
    {
        //cout<<"key:";
        showString(strPair.first);
        cout<<"; value:";
        showString(strPair.second);
        cout<<endl;
        //cout <<tableColumn1<<total<<tableColumn2<<str<<tableColumn3<<subDir<<tableColumn4<<endl;
    }
};

void showString(const string& str)
{
    for (int i = 0; i < str.size(); i ++)
    {
        unsigned char ch = str[i];
        cout<<ch;
        //cout.flush();
    }
}

void showMap(const StringMap& stringMap)
{
    cout<<header1<<header2<<header3<<endl;
    cout<<tableHeader1<<tableHeader2<<endl;
    cout<<comment1<<prefix<<comment2<<endl;
    int counter = 1;
    for (StringMap::const_iterator it =  stringMap.begin(); it != stringMap.end(); it ++)
    {
        cout << tableColumn1 << counter << tableColumn2;
        showString(it->second);
        cout << tableColumn3;
        showString(it->first);
        cout << tableColumn4;
        counter ++;
    }
    cout<< bottom<<endl;
}



int main()
{
    path srcPath("/media/unused/diabloforum");
    //path srcPath("/media/unused/diabloforum/DC/HWBooks/Serial Communications Dev guide");
    //path srcPath("/media/unused/USB Design By Example");

    //path dstPath = srcPath.parent_path() / "dst";
    StringMap stringMap;

    doDir(srcPath, stringMap, prefix);

    //for_each(stringMap.begin(), stringMap.end(), ShowStringPair());
    showMap(stringMap);
    return 0;
}








/*
void copy_directory(const path& src, const path& dst)
{
    if (is_directory(src) && is_directory(dst))
    {
        directory_iterator srcIt(src), itEnd;
        while (srcIt != itEnd)
        {
            path dstPath = dst / srcIt->filename();
            //cout<<"src="<<srcIt->filename() <<endl<<"dst="<<dstPath->filename()<<endl;

            if (is_regular_file(*srcIt))
            {
                copy_file(*srcIt, dstPath);
            }
            else
            {
                if (is_directory(*srcIt))
                {
                    create_directory(dstPath);
                    copy_directory(*srcIt, dstPath);
                }
            }
            srcIt ++;
        }
    }
}


int main()
{
    path srcPath("/home/nick/myprojects/mytest");
    path dstPath = srcPath.parent_path() / "dst";
    cout<<srcPath.filename().c_str()<<endl;

    //doDir(srcPath);
    if (! exists(dstPath))
    {
        create_directory(dstPath);
    }

    if (is_directory(dstPath))
    {
        copy_directory(srcPath, dstPath);
    }

    //copy_directory(srcPath, dstPath);
    return 0;
}
*/







                                 back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)