Superb quality and spec AB-Com PULSe 4K SE. Crazy offer! Only £99! FREE UK DELIVERY! 4K UHD, Enigma 2, Multiboot 4 images & more!...
Superb quality and spec AB-Com PULSe 4K Rev II Twin Satellite tuner only £149! FREE UK DELIVERY! 4K UHD, Enigma 2, SATA HDD facility, Multiboot 4 images & more!...

[OS-mio] Crash when folder contains filenames with Windows encoding

name is str in getItemDisplayName. But what is IMPORTANT here, "filename" is still intact inside str, it's just in different format.
A Python str is an array of Unicode points. How did you get a filename in there that might not have been valid utf8 in the first place?
 
A Python str is an array of Unicode points. How did you get a filename in there that might not have been valid utf8 in the first place?
I don't know what you mean "How did you". We are working on the code in the repo. We haven't done anything to create that behaviour. It was already there.
 
I got it working! Attatched all modifications I currently have and files are playing fine! (service.cpp function is copy/pasted, sorry)

Also have very good news. It's NOT required to change any python functions to use bytes. Escaped characters in str can be handled using typemaps.
 

Attachments

It's NOT required to change any python functions to use bytes. Escaped characters in str can be handled using typemaps.
Does that mean we don't need the changes in MovieList at all?
 
Yes, but that change also affected MovieSelection.py, because there is "from Components.MovieList import getItemDisplayName".

movielist.py change was only intended for 3 cases "data.txt" in movielist.py, so I changed movielist.py little.

What about the copy/paste? Is there a nicer way to do that?
I also googled, but did not find obvious ways to do that. It seems it's not possible to call constructor from outside.

Also it should be possible to add these typemaps to original functions, then these extra char* functions would not be needed. (So far attempt has been unsuccessful)
 
So the problem with the copy/paste version is we now have duplicate code which would need maintaining in synchronisation. Bit of a nightmare. :(

Code:
eServiceReference::eServiceReference(const char* string2)
{
	std::string string(string2);
	eDebug("[eServiceReference][char]");
	eServiceReference(string);
}

Code:
| service/service.cpp: In constructor 'eServiceReference::eServiceReference(const char*)':
| service/service.cpp:121:26: warning: unnecessary parentheses in declaration of 'string' [-Wparentheses]
|   121 |         eServiceReference(string);
|       |                          ^~~~~~~~
| service/service.cpp:121:26: note: remove parentheses
|   121 |         eServiceReference(string);
|       |                          ^~~~~~~~
|       |                          -      -
| service/service.cpp:121:27: error: conflicting declaration 'eServiceReference string'
|   121 |         eServiceReference(string);
|       |                           ^~~~~~

So looks like it doesn't understand we are calling the function.

Is this problem caused because someone thought it would be a good idea to give the class and the function the same name?
 
Ok, playing a bit more...

In iservice.h:
Code:
	eServiceReference(int type, int flags, const std::string &path)
		: type(type), flags(flags), path(path)
	{
		memset(data, 0, sizeof(data));
		number = 0;
	}
+	[B]void eServiceReferenceBase(const std::string &string);[/B]
	eServiceReference(const std::string &string);
	eServiceReference(const char* string2);
	std::string toString() const;
	std::string toCompareString() const;

In service.cpp:
Code:
	}
	return res;
}

-[B]eServiceReference::eServiceReference(const std::string &string)[/B]
+[B]void eServiceReference::eServiceReferenceBase(const std::string &string)[/B]
{
	const char *c = string.c_str();
	int pathl = 0;

Then add this in service.cpp:
Code:
eServiceReference::eServiceReference(const std::string &string)
{
	eDebug("[eServiceReference][std]");
	eServiceReferenceBase(string);
}

eServiceReference::eServiceReference(const char* string2)
{
	std::string string(string2);
	eDebug("[eServiceReference][char]");
	eServiceReferenceBase(string);
}
 
I don't know what you mean "How did you". We are working on the code in the repo. We haven't done anything to create that behaviour. It was already there.
It's an anonymous you. I could have written "How did one".

I'm intrigued as to how bytes end up in a str given things like:

Code:
 >>> bstr = b'\x86\x87\x88'
>>> ustr = bstr.decode() 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 0: invalid start byte
 
I'm intrigued as to how bytes end up in a str given things like:
Code:
 >>> bstr = b'\x86\x87\x88'
>>> ustr = bstr.decode() 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 0: invalid start byte
bstr = b'\x86\x87\x88'
ustr = bstr.decode('UTF-8', 'surrogateescape')

Ofcourse this is python only string format. When this string is sent to SWIG, it sees escaped characters and throws exception. But they can be converted back to bytes using typemap.
 
Last edited:
Ok, playing a bit more...

In iservice.h:
Code:
	eServiceReference(int type, int flags, const std::string &path)
		: type(type), flags(flags), path(path)
	{
		memset(data, 0, sizeof(data));
		number = 0;
	}
+	[B]void eServiceReferenceBase(const std::string &string);[/B]
	eServiceReference(const std::string &string);
	eServiceReference(const char* string2);
	std::string toString() const;
	std::string toCompareString() const;

In service.cpp:
Code:
	}
	return res;
}

-[B]eServiceReference::eServiceReference(const std::string &string)[/B]
+[B]void eServiceReference::eServiceReferenceBase(const std::string &string)[/B]
{
	const char *c = string.c_str();
	int pathl = 0;

Then add this in service.cpp:
Code:
eServiceReference::eServiceReference(const std::string &string)
{
	eDebug("[eServiceReference][std]");
	eServiceReferenceBase(string);
}

eServiceReference::eServiceReference(const char* string2)
{
	std::string string(string2);
	eDebug("[eServiceReference][char]");
	eServiceReferenceBase(string);
}

By the way, I forgot to say, this does actually work.
 
MovieList still has to be changed. I posted change earlier today and zip has this change included.

So what goes wrong without the MovieList change now we have the new code in iservice.h/service.cpp? Can you test with the old MovieList.py and new cpp code please?
 
bstr = b'\x86\x87\x88'
ustr = bstr.decode('UTF-8', 'surrogateescape')

Ofcourse this is python only string format. When this string is sent to SWIG, it sees escaped characters and throws exception. But they can be converted back to bytes using typemap.
Seems a convoluted (and hence error prone) way to keep data when it is always actually a bytes format.
 
Seems a convoluted (and hence error prone) way to keep data when it is always actually a bytes format.

We are just working with what python/SWIG developers dropped in our laps.
 
Seems a convoluted (and hence error prone) way to keep data when it is always actually a bytes format.

Huevos is correct its what the python 3 Developers have given us, bless them!
Also there are bytes and bytes - with Unicode you have be careful with text files and their manipulation, as a unicode character can in theory occupy upto 4 bytes in utf-8, so memory manipulation can typically occupy 2 x memory compared to python 2 and be slower with older python 2 methods of manipulation.
 
So what goes wrong without the MovieList change now we have the new code in iservice.h/service.cpp? Can you test with the old MovieList.py and new cpp code please?
Without movielist changes it crashes same way as in post #1.

data.txt is inside larger object/structure, it's not a function parameter. Typemaps can only handle function parameters.

It should also be easy to test yourself too. Take any videofile, check that it plays fine. Edit filename to contain b'\xe4' for example.
 
Last edited:

OpenViX Feeds Status

Back
Top