Функция для проверки имени файла


Эта функция проверяет, если имя файла является допустимым или нет. Я думаю, что это не достаточно хорошо для интеграции (не оптимизирована, может я забыл про какие-то проверки), поэтому нужны ваши комментарии.

static
int ReservedName( const char * name )
{
    char * reservedFileNames[] = { "CON",  "PRN",  "AUX",  "NUL",
                                   "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
                                   "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };

    char * reservedFileNamesWithDot[] = { "CON.",  "PRN.",  "AUX.",  "NUL.",
                                          "COM1.", "COM2.", "COM3.", "COM4.", "COM5.", "COM6.", "COM7.", "COM8.", "COM9.",
                                          "LPT1.", "LPT2.", "LPT3.", "LPT4.", "LPT5.", "LPT6.", "LPT7.", "LPT8.", "LPT9." };

    int i;
    int n = sizeof( reservedFileNames ) / sizeof( reservedFileNames[0] );

    for( i = 0; i < n; i++ )
    {
        if( stricmp( reservedFileNames[i], name ) == 0 ) 
        {
            return 1;

        }else{

            if( strnicmp( reservedFileNamesWithDot[i], name, strlen( reservedFileNamesWithDot[i] ) ) == 0 )
            {
                return 1;
            }
        }
    }

    return 0;
}


static
int GetCharsNumInPath( IN const char * path )
{
    int i, cnt;

    for( i = 0; path[i]; i++ )
    {
        if( ( path[i] < 0x80 ) || ( path[i] > 0xbf ) )
            cnt++;
    }

    return cnt;
}


int ValidName( const char * name )
{
    if( name != NULL )
    {
        if( GetCharsNumInPath( path ) <= MAX_PATH )
        {
            if( ! ReservedName( name ) )
            {
                int i;
                int n = strlen( path );

                for( i = 0; i < n; i++ )
                {
                    switch( path[i] )
                    {
                        // ? " / < > * |
                        // these characters can not be used in file or folder names
                        //
                        case '<':
                        case '>':
                        case '/':
                        case '\\':
                        case '\"':
                        case '?':   
                        case '*':
                        case '|':
                            return 0;

                        case ' ':
                        case '.':
                        {
                            if( ( i + 1 == n ) )
                            {
                                return 0;

                            }else{

                                continue;
                            }
                        }
                    }
                }

                return 1;

            }else{ // if( ! ReservedName( name ) )

                return 0;
            }

        }else{ // if( GetCharsNumInPath( IN path ) <= MAX_PATH_LEN )

            return 0;
        }

    }else{ // if( name != NULL )

        return 0;
    }
}


3382
2
задан 20 августа 2011 в 11:08 Источник Поделиться
Комментарии
2 ответа

Каждый имеет их собственную сторону священной войны о том, где '{' должны быть.

Но одна вещь, все согласны на том, что вы должны быть последовательны.
В вашем коде вы совместите открывать и закрывать (что я считаю идеальным) за исключением случаев, когда вы используете другое

   }else{

Остаюсь при том же стиле, что и остальной части вашего кода

   }
else
{

Если ваш 2 массивов должны быть идентичны, то вы должны, вероятно, нет двух разных массивов. Вы должны, вероятно, использовать один массив и использовать код, чтобы получить дополнительную функциональность. В противном случае вас с головой в проблемы обслуживания, где каждый дополнение к одному массива должны быть отражены в дополнение к другой массив (и вы должны проверить, что они одинаковые).

char * reservedFileNames[] = { "CON",  "PRN",  "AUX",  "NUL",
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };

size_t wordLen = strlen( reservedFileNames[i]);
if( stricmp( reservedFileNames[i], name, wordLen) == 0 )
{
if (name[wordLen] == '\0') // The strings are technically equal
{ return 1;
}
if (name[wordLen] == '.') // The string has a bad prefix.
{ return 1;
}
}

2
ответ дан 20 августа 2011 в 04:08 Источник Поделиться

Я не уверен, что вы используете для этого, но мой совет: не заморачивайтесь проверка именем. Просто откройте файл. Система знает правила лучше, чем вы, и добавив слишком много проверки вы можете вызвать проблемы вниз по линии.

На Windows эти правила являются особенно сложными. Честно говоря, вы никогда не найдете их всех. Вот несколько, которые вы пропустили, с верхней части моей головы:


  • Имена файлов могут содержать символы Unicode. Вы используете символ*. Если вы используете UTF-8 и передает все ваши имена не менее multibytetowidechar , прежде чем они достигнут файл API, вы исключили много возможных допустимых путей на основе этого. (Не говоря уже о то, как эти имена будут переклассифицированы в Unicode теперь в зависимости от настроек языка пользователя, которого можно спорить-это плохо по-своему прав...)

  • В max_path. Ты считаешь, что все пути поместится в буфер такого размера. На Windows вы можете на самом деле есть путь больше, чем в max_path , если он начинается с \\?\; также такие вещи, как \\?\C:\foo допустимы пути.

  • Имена, содержащие пробелы или точки, которые вы, кажется, фильтрацию, также действительны и различны, если путь начинается с \\?. Без этого префикса, точки и пробелы обрезались.

  • Пути под \\.\, \\?\GLOBALROOT.

Не говоря, эти правила потенциально могут быть изменены. Обратите внимание, что в Win9x были разные правила, чем НТ. Что если такое изменение произойдет снова и ломает вашу логику? Не беспокойтесь дублировать эти правила в ваш код, не том, файловую систему. Просто передать имя функции CreateFile.

(В сторону: если вашим именем, случается, приходят из ненадежного источника, то это, вероятно, справедливо быть чрезмерно ограничительными...)

6
ответ дан 22 августа 2011 в 05:08 Источник Поделиться