Make CheckFilename behave differently on different OSs

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Quin
Addict
Addict
Posts: 1133
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Make CheckFilename behave differently on different OSs

Post by Quin »

This could maybe be put behind a flag to not break (rare) old code, but IMO the way CheckFilename works is fundamentally flawed.
If I understand how it works correctly, if I pass it a path like "/home/quin" on Linux, it'll return #False because / isn't allowed in filenames on Windows...
This is also written in the docs:
Even if the syntax-check of this function doesn't complain, there are different 'forbidden' filenames on different OS. For example on Windows filenames containing "COM1" till "COM9", "LPT1" till "LPT9" or "aux" are not allowed. For more information see here.
I think it would be better if this function returned different results for all the different OSs, e.g. / shouldn't make it return false on Linux. :idea:
AZJIO
Addict
Addict
Posts: 2191
Joined: Sun May 14, 2017 1:48 am

Re: Make CheckFilename behave differently on different OSs

Post by AZJIO »

It is necessary to clarify what a "Filename" is. I think "Filename" and "Path" are different things.
Quin
Addict
Addict
Posts: 1133
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Make CheckFilename behave differently on different OSs

Post by Quin »

Filenames often come at the end of paths ;)
Sure, there's GetFilePart(), but if this function is only meant for filenames *without* any parent directories, that needs to be clearly stated IMO.
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Make CheckFilename behave differently on different OSs

Post by BarryG »

The manual says CheckFilename() is "the filename to check without a path", so don't include the path. ;)
Quin
Addict
Addict
Posts: 1133
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Make CheckFilename behave differently on different OSs

Post by Quin »

Derp.
That's the problem with reading at 900 words a minute.
Sometimes you miss things.
So, to amend the feature request: on Windows, can it detect those special filenames, such as COM1, COM2 etc?
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Make CheckFilename behave differently on different OSs

Post by BarryG »

Those special filenames are reserved in Windows, so they're not available and CheckFilename() will rightfully return 0. Try creating a file in Windows (not from PureBasic) with one of those names and you'll see that the OS rejects it (https://learn.microsoft.com/en-us/windo ... ing-a-file).

Technically, the CheckFilename() command could be updated to internally remove the path before checking, like this:

Code: Select all

Debug CheckFilename(GetFilePart(path_and_file$))
So your request isn't so bad if it's done this way. :)
AZJIO
Addict
Addict
Posts: 2191
Joined: Sun May 14, 2017 1:48 am

Re: Make CheckFilename behave differently on different OSs

Post by AZJIO »

BarryG wrote: Thu May 22, 2025 2:29 am So your request isn't so bad if it's done this way. :)
Don't forget that when you add 90 protections against stupid user actions, you make the function 90 times slower. Many will build in the necessary protections on their own and only those that are necessary.
Last edited by AZJIO on Thu May 22, 2025 3:55 am, edited 1 time in total.
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Make CheckFilename behave differently on different OSs

Post by BarryG »

Fair call.
AZJIO
Addict
Addict
Posts: 2191
Joined: Sun May 14, 2017 1:48 am

Re: Make CheckFilename behave differently on different OSs

Post by AZJIO »

Code: Select all

EnableExplicit

Procedure CheckPath(*c.Character)
	Protected i, slash, flag = #True
	
	If *c = 0 Or *c\c = 0
		ProcedureReturn #False
	EndIf
	
	While *c\c
		i + 1
		Select i
			Case 1
				If Not ((*c\c >= 'a' And *c\c <= 'z') Or (*c\c >= 'A' And *c\c <= 'Z'))
					flag = #False
					Break
				Else
					*c + SizeOf(Character)
					Continue
				EndIf
			Case 2
				If *c\c <> ':'
					flag = #False
					Break
				Else
					*c + SizeOf(Character)
					Continue
				EndIf
			Case 3
				If *c\c <> '\'
					flag = #False
					Break
				Else
					slash = 1
					*c + SizeOf(Character)
					Continue
				EndIf
		EndSelect
		Select *c\c
			Case '\'
				If slash
					flag = #False
					Break
				EndIf
				slash = 1
			Case '<', '>', '?', '|', '*', '"', ':'
				flag = #False
				Break
			Default
				slash = 0
		EndSelect
		*c + SizeOf(Character)
	Wend
	
	ProcedureReturn flag
EndProcedure

Define path$
path$ = "C:\PB\PureBasic\PureBasic_x64\Compilers"
Debug CheckPath(@path$)
path$ = "C:\PB\PureBasic\\PureBasic_x64\Compilers"
Debug CheckPath(@path$)
path$ = "C:\PB\PureBasic:PureBasic_x64\Compilers"
Debug CheckPath(@path$)
path$ = "C:\Users\<user>\AppData"
Debug CheckPath(@path$)
path$ = "%temp%"
Debug CheckPath(@path$)
version 2

Code: Select all

EnableExplicit

Procedure CheckPath(*c.Character)
	Protected i, slash, flag = #True
	
	If *c = 0 Or *c\c = 0
		ProcedureReturn #False
	EndIf
	
	While *c\c
		i + 1
		If i = 1
			If Not ((*c\c >= 'a' And *c\c <= 'z') Or (*c\c >= 'A' And *c\c <= 'Z'))
				flag = #False
				Break
			Else
				*c + SizeOf(Character)
				If *c\c <> ':'
					flag = #False
					Break
				Else
					*c + SizeOf(Character)
					If *c\c <> '\'
						flag = #False
						Break
					Else
						slash = 1
						*c + SizeOf(Character)
						Continue
					EndIf
				EndIf
			EndIf
		EndIf
		Select *c\c
			Case '\'
				If slash
					flag = #False
					Break
				EndIf
				slash = 1
			Case '<', '>', '?', '|', '*', '"', ':'
				flag = #False
				Break
			Default
				slash = 0
		EndSelect
		*c + SizeOf(Character)
	Wend
	
	ProcedureReturn flag
EndProcedure

Define path$
path$ = "C:\PB\PureBasic\PureBasic_x64\Compilers"
Debug CheckPath(@path$)
path$ = "C:\PB\PureBasic\PureBasic_x64\Compilers\"
Debug CheckPath(@path$)
path$ = "C:\"
Debug CheckPath(@path$)
; Error
path$ = "C:"
Debug CheckPath(@path$)
path$ = "C:\\"
Debug CheckPath(@path$)
path$ = "C:\PB\PureBasic\\PureBasic_x64\Compilers"
Debug CheckPath(@path$)
path$ = "C:\PB\PureBasic:PureBasic_x64\Compilers"
Debug CheckPath(@path$)
path$ = "C:\Users\<user>\AppData"
Debug CheckPath(@path$)
path$ = "%temp%"
Debug CheckPath(@path$)
Regular expression

Code: Select all

EnableExplicit

Procedure CheckPath(path$)
	Protected id_re, flag = #True
	
	id_re = CreateRegularExpression(#PB_Any, "\A[a-z]:(\\[^\\/:*?" + Chr(34) + "<>|]+)*?\\?\z", #PB_RegularExpression_NoCase)
	If id_re
		If Not MatchRegularExpression(id_re, path$)
			flag = #False
		EndIf
		FreeRegularExpression(id_re)
	EndIf
	
	ProcedureReturn flag
EndProcedure

Define path$
path$ = "C:\PB\PureBasic\PureBasic_x64\Compilers"
Debug CheckPath(path$)
path$ = "C:\PB\PureBasic\PureBasic_x64\Compilers\"
Debug CheckPath(path$)
path$ = "C:\"
Debug CheckPath(path$)
; Error
path$ = "C:\\"
Debug CheckPath(path$)
path$ = "C:\PB\PureBasic\\PureBasic_x64\Compilers"
Debug CheckPath(path$)
path$ = "C:\PB\PureBasic:PureBasic_x64\Compilers"
Debug CheckPath(path$)
path$ = "C:\Users\<user>\AppData"
Debug CheckPath(path$)
path$ = "%temp%"
Debug CheckPath(path$)
User avatar
NicTheQuick
Addict
Addict
Posts: 1519
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Make CheckFilename behave differently on different OSs

Post by NicTheQuick »

On Linux that command would be quite simple. Only the null character and `/` are not allowed in filenames. But all the other Unicode characters are allowed. On Windows it is more complicated.

To be precise, it's not just the operating system, but also the file system. If you use NTFS or FAT32 under Linux, the characters there are also limited. This means that, technically speaking, you would actually have to pass an entire path to `CheckFilename()` and the function would then have to check internally which file system the file is on and react accordingly.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Post Reply