Comments (12)
Hm, this is beyond my limited knowledge of UPnP. At a guess I'd say that it looks like the server isn't decoding the XML properly. Could you check what the payload looks like that is sent to the server?
To check this, at this point in your local copy of this library:
https://github.com/huin/goupnp/blob/master/soap/soap.go#L40
Put this code:
fmt.Println(string(requestBytes))
I'm expecting that you will see a part of it looking like this:
...<SearchCriteria>(dc:title contains "star wars") ...
This is valid, and a correct XML encoding of the query. But if the server doesn't decode it properly then the "
are being read literally. If that's the case, then things might be tricky, as I'm not sure how to get the Go XML library to not escape the double quotes. You could try using single quotes instead, but I rather suspect that they would be similarly escaped as well.
from goupnp.
Hi Huin
you're right the soap envelop convert the quote to " html code.
But when I see the specification, searchCriteria wait for quote or double quote and not html code.
http://upnp.org/specs/av/UPnP-av-ContentDirectory-v1-Service.pdf
Simple quote or double are converted.
How can I bypass the conversion ?
Best regards
Jerome
from goupnp.
As goupnp stands right now, you won't be able to bypass it, the library will have to be changed to make this work. My interpretation of the spec would be that it should accept XML entities (otherwise how would the relOp
part of the grammar allow for literal <
without breaking the XML it's embedded within.
Looking at https://golang.org/pkg/encoding/xml/#Marshal I'm thinking that it might be possible to tag the outgoing data elements encoded as text in XML as innerxml
, and arrange for the value passed to be only escaping <
, >
, and &
, which are the absolute minimum to be escaped and not do dangerous things in XML text elements (but crucially not "
or '
, which should only need to be escaped within an XML tag). This should still be acceptable and safe XML and meet your immediate needs.
This would affect all the generated code, such as the code here:
https://github.com/huin/goupnp/blob/master/dcps/av1/av1.go#L2423
A quick hack to see if this approach would work for you would be to edit (but not commit) the file above to change the (current) line 2428 from
SearchCriteria string
to
SearchCriteria string `xml:",innerxml"`
(Note that those are backticks, not single quotes, and the comma is not a typo)
See if that solves this specific case you have and let me know. Note that this is not a complete solution, as:
a) We need to change the code generator to do this in future.
b) This will break the XML as soon as a <
, >
, or &
appears in the search criteria (although I wonder how your media server will cope with that case without this change -- I'd be interested in knowing).
from goupnp.
If possible, could you test branch server-xml-workaround
? I'm hoping that this is a functional workaround for the problem.
from goupnp.
Hi Huin,
well, the issue comes from the line 129 of the file soap. The EncodeElement function of the xml encoder escape string.
I see no solution for the moment.
Thanks a lot for the branch, I tested with it, but same result.
Jerome
from goupnp.
Hi Huin,
I find a workaround, I create my own soap client like this :
`var URN_ContentDirectory_1 = "urn:schemas-upnp-org:service:ContentDirectory:1"
type SoapEnvelope struct {
XMLName xml.Name xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"
Body *SoapBody
}
type SoapFault struct {
Faultstring string
Detail string
}
type SoapBody struct {
XMLName xml.Name xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"
Fault *SoapFault
Search *UpnpContentDirectorySearchRequest xml:"urn:schemas-upnp-org:service:ContentDirectory:1 Search"
SearchResponse *UpnpContentDirectorySearchResponse xml:"urn:schemas-upnp-org:service:ContentDirectory:1 SearchResponse"
}
type UpnpContentDirectoryClient struct {
Url *url.URL xml:"-"
}
func NewUpnpContentDirectoryClient(url *url.URL) (*UpnpContentDirectoryClient) {
return &UpnpContentDirectoryClient{Url: url}
}
func (c *UpnpContentDirectoryClient) Search(ContainerID string, SearchCriteria string, Filter string, StartingIndex string, RequestedCount string, SortCriteria string) (Result string, NumberReturned uint32, TotalMatches uint32, UpdateID uint32, err error) {
search := &UpnpContentDirectorySearchRequest{
ContainerID: ContainerID,
SearchCriteria: ""+SearchCriteria+"",
Filter: Filter,
StartingIndex: StartingIndex,
RequestedCount: RequestedCount,
SortCriteria: SortCriteria,
}
env := &SoapEnvelope{Body:&SoapBody{Search:search,Fault:nil}}
w := &bytes.Buffer{}
err = xml.NewEncoder(w).Encode(env)
if err != nil {
fmt.Println(err)
return "",0,0,0,err
}
fmt.Printf("Envelope SOAP:%s",string(w.String()))
httpClient := &http.Client{}
httpRequest,err := http.NewRequest("POST",c.Url.String(),bytes.NewBuffer(w.Bytes()))
if err != nil {
fmt.Printf("%v",err)
return "",0,0,0,err
}
httpRequest.Header.Set("SOAPACTION","
+ URN_ContentDirectory_1 + #Search"
)
httpRequest.Header.Set("CONTENT-TYPE","text/xml; charset="utf-8"")
httpResponse,err := httpClient.Do(httpRequest)
if err != nil {
fmt.Printf("%v",err)
return "",0,0,0,err
}
if httpResponse.StatusCode != 200 {
fmt.Printf("%v",httpResponse)
return "",0,0,0,errors.New("http code "+ httpResponse.Status)
}
defer httpResponse.Body.Close()
response := &SoapEnvelope{}
err = xml.NewDecoder(httpResponse.Body).Decode(response)
if err != nil {
fmt.Println(err)
return "",0,0,0,err
}
sr := response.Body.SearchResponse
return sr.Result,sr.NumberReturned,sr.TotalMatches,sr.UpdateID,nil
}
type UpnpContentDirectorySearchRequest struct {
ContainerID string xml:"ContainerID"
SearchCriteria string xml:",innerxml"
Filter string xml:"Filter"
StartingIndex string xml:"StartingIndex"
RequestedCount string xml:"RequestedCount"
SortCriteria string xml:"SortCriteria"
}
type UpnpContentDirectorySearchResponse struct {
Result string
NumberReturned uint32
TotalMatches uint32
UpdateID uint32
}
type DIDLLite struct {
XMLName xml.Name
DC string xml:"xmlns:dc,attr"
UPNP string xml:"xmlns:upnp,attr"
XSI string xml:"xmlns:xsi,attr"
XLOC string xml:"xsi:schemaLocation,attr"
Objects []Object xml:"item"
}
type Object struct {
ID string xml:"id,attr"
Parent string xml:"parentID,attr"
Restricted string xml:"restricted,attr"
Title string xml:"title"
Creator string xml:"creator"
Class string xml:"class"
Date string xml:"date"
Results []Res xml:"res"
}
type Res struct {
Resolution string xml:"resolution,attr"
Size uint64 xml:"size,attr"
ProtocolInfo string xml:"protocolInfo,attr"
Duration string xml:"duration,attr"
Bitrate string xml:"bitrate,attr"
SampleFrequency uint64 xml:"sampleFrequency"
NrAudioChannels uint64 xml:"nrAudioChannels"
Value string xml:",chardata"
}`
and I can get the results from my device media server.
Thanks for your time and your advises.
Jerome
from goupnp.
Ah yes, I'd completely forgotten that I'd written that bit of code. I guess that actually makes things easier, but I'll have to try again later when I get a moment.
from goupnp.
No problem Huin,
I'll stay tuned ;).
You can close this issue.
Jerome
from goupnp.
I've had another crack at this in branch server-xml-workaround-2
. I feel a bit more confident about this as it actually had an existing test.
from goupnp.
Hi Huin,
I've tested and it works as expected.
You fixed my issue.
Thanks for your time.
Jerome
from goupnp.
Excellent, thanks for the report and confirmation. I'll get this merged into master.
from goupnp.
Fixed in 991e174.
from goupnp.
Related Issues (20)
- Unable to find devices most of the time HOT 7
- It's not possible to query ssdp:all HOT 1
- Incorrect err (nil) returned incase of timeout in httpu HOT 6
- Discover UPnP as not active if UPnP not ON in device HOT 4
- Show devices connected to discovered UPnP enabled device. HOT 2
- Why can't i find this upnp device (http://192.168.61.1:5000/rootDesc.xml)? HOT 5
- GetTotalBytesSent() can't parse value, if it's negative HOT 3
- Fail on http post request to router. HOT 12
- httpu multicast fails on multiple interfaces HOT 7
- Please provide example of AV dlna device implementation (audio) HOT 2
- Could you specify some examples? HOT 10
- Making charset dependency optional HOT 6
- SSDPRawSearch: With the same USN, ipv4Response was replaced by ipv6Response, which is not effected for ipv4only client. HOT 1
- Contexts on HTTP calls HOT 6
- httpu: error while parsing response HOT 4
- Any plan to add SSDP Server Support ? HOT 1
- get the IP associated with the interface used to successfully discover the upnp setup ? HOT 26
- feat: context everywhere and non-blocking results HOT 2
- update the guide HOT 1
- Provide an API to use specific ip addresses for discovery HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from goupnp.