@@ -695,25 +695,64 @@ static PyObject *dmidecode_xmlapi(PyObject *self, PyObject *args)
695695 xmlDoc * temp_doc = NULL ;
696696 xmlNode * dmixml_n = NULL ;
697697 xmlChar * xml_buffer = NULL ;
698- char * sect_query = NULL , * qtype = NULL , * rtype = NULL ;
698+ const char * sect_query = NULL , * qtype = NULL , * rtype = NULL ;
699+ PyObject * third_arg = NULL ;
699700 int type_query = -1 ;
700701 int buffer_size = 0 ;
701702
702- // Parse arguments - we use a simpler interface for compatibility
703- if ( !PyArg_ParseTuple (args , "ss|si" , & qtype , & rtype , & sect_query , & type_query ) ) {
703+ // Parse arguments.
704+ // We support both of these call shapes:
705+ // xmlapi('s', rtype, section)
706+ // xmlapi('t', rtype, typeid)
707+ // And the legacy 4-arg variant:
708+ // xmlapi('t', rtype, section_placeholder, typeid)
709+ if ( !PyArg_ParseTuple (args , "ss|Oi" , & qtype , & rtype , & third_arg , & type_query ) ) {
704710 return NULL ;
705711 }
706712
713+ if ( third_arg == Py_None ) {
714+ third_arg = NULL ;
715+ }
716+
707717 // Check for sensible arguments and retrieve the xmlNode with DMI data
708718 switch ( * qtype ) {
709719 case 's' : // Section / GroupName
720+ if ( third_arg == NULL ) {
721+ PyReturnError (PyExc_TypeError , "section argument cannot be NULL" )
722+ }
723+ if ( PyUnicode_Check (third_arg ) ) {
724+ sect_query = PyUnicode_AsUTF8 (third_arg );
725+ } else if ( PyBytes_Check (third_arg ) ) {
726+ sect_query = PyBytes_AsString (third_arg );
727+ } else {
728+ PyReturnError (PyExc_TypeError , "section argument must be str or bytes" )
729+ }
710730 if ( sect_query == NULL ) {
711- PyReturnError (PyExc_TypeError , "section keyword cannot be NULL" )
731+ // Exception already set by PyUnicode_AsUTF8() or PyBytes_AsString()
732+ return NULL ;
712733 }
713734 dmixml_n = __dmidecode_xml_getsection (global_options , sect_query );
714735 break ;
715736
716737 case 't' : // TypeID / direct TypeMap
738+ // Prefer a positional typeid in the third slot.
739+ if ( third_arg != NULL ) {
740+ if ( PyLong_Check (third_arg ) ) {
741+ long v = PyLong_AsLong (third_arg );
742+ if ( PyErr_Occurred () ) {
743+ return NULL ;
744+ }
745+ type_query = (int ) v ;
746+ } else if ( type_query < 0 && (PyUnicode_Check (third_arg ) || PyBytes_Check (third_arg )) ) {
747+ // Backwards compatibility: allow typeid passed as string.
748+ const char * s = PyUnicode_Check (third_arg ) ? PyUnicode_AsUTF8 (third_arg )
749+ : PyBytes_AsString (third_arg );
750+ if ( s == NULL ) {
751+ return NULL ;
752+ }
753+ type_query = atoi (s );
754+ }
755+ }
717756 if ( type_query < 0 ) {
718757 PyReturnError (PyExc_TypeError ,
719758 "typeid keyword must be set and must be a positive integer" );
0 commit comments