Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rfc2045 decode #171

Merged
merged 3 commits into from
Feb 1, 2022
Merged

Rfc2045 decode #171

merged 3 commits into from
Feb 1, 2022

Conversation

tbrk
Copy link
Contributor

@tbrk tbrk commented Jan 30, 2022

Some XML-RPC servers break Base64 encoded data into lines of 76 characters long (see, e.g., the Python xmlrpc library). In these cases the Base64.decode_exn function raises an exception Invalid_argument "Malformed input".

I propose, in this pull request, to decode using the Base64_rfc2045 module which handles newlines. This module also decodes base64 strings without line breaks (in "dangerous" mode) and thus supports existing behavior.

@mseri
Copy link
Collaborator

mseri commented Jan 31, 2022

I think this should be made configurable, maybe it is better to see first how this is going to be addressed in ocaml-base64

@tbrk
Copy link
Contributor Author

tbrk commented Jan 31, 2022

What would you think about allowing the caller to provide a decode function (defaulting to Base64.decode), either by threading an argument down to the point where decoding happens or using a module-level reference to set the decoding function?

@tbrk
Copy link
Contributor Author

tbrk commented Jan 31, 2022

As it stands it's not possible to use ocaml-rpc to interact with a server written in Python (using the xmlrpc library) that returns a base64-encoded value.

@mseri
Copy link
Collaborator

mseri commented Jan 31, 2022

I understand the reason behind the PR. As per the solution, I think it would be fine to provide an optional decoder parameter, which uses the current one by default but allows you to pass in anything else. We could also expose the current Base64_rfc2045 one, so that there is already the alternative available

src/lib/rpc.ml Outdated Show resolved Hide resolved
@tbrk
Copy link
Contributor Author

tbrk commented Jan 31, 2022

OK. I agree with you that some kind of parameterization is necesary to handle all the different cases (no line breaks, line breaks every 76 characters with \r\n, line breaks every 76 characters with \n, etc.). I'll draft a solution and include the suggested comment and documentation. Thanks @mseri.
My current suggestion is a nasty hack.

@mseri
Copy link
Collaborator

mseri commented Jan 31, 2022

Thanks for the contribution

@tbrk
Copy link
Contributor Author

tbrk commented Jan 31, 2022

This commit allows callers of Xmlrpc to override the function used to decode base64 values. It has the advantage of externalizing the decoding strategy. I guess the correct place for base64 decoding functions is in ocaml-base64.
I did not update Rpc and Rpcmarshal, but I can do this if you would like. I'm not sure how useful the override option is in these cases.

@tbrk
Copy link
Contributor Author

tbrk commented Jan 31, 2022

I've updated my proof of concept to use the proposed interface.

@@ -22,40 +22,58 @@ val a_of_response

exception Parse_error of string * string * Xmlm.input

(* The parsing functions make it possible to specify the routine used to
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(* The parsing functions make it possible to specify the routine used to
(** The parsing functions make it possible to specify the routine used to

Let’s have this in the documentation

let make_enum = make (fun data -> Enum data)
let make_dict = make (fun data -> Dict data)

(* General parser functions *)
let rec of_xml ?callback accu input =
try value (map_tags (basic_types ?callback accu)) input with
let rec of_xml ?callback ?base64_decode accu input =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let rec of_xml ?callback ?base64_decode accu input =
let rec of_xml ?callback ?base64_decoder accu input =

I am bikeshedding here, but I would usebase64_decoder as parameter name

@mseri
Copy link
Collaborator

mseri commented Feb 1, 2022

Thanks. I like this.

I think it makes sense to leave it only on the xmlrpc module right now. I would copy your little implementation of the base 64 decoder and maybe add a comment in the Readme or the documentation showing it and why it can be useful when communicating with python. But I can do that myself before releasing, after this is merged.

thanks a lot for the contributions

@tbrk
Copy link
Contributor Author

tbrk commented Feb 1, 2022

Thanks for your suggestions and maintainership! I think the final result we arrived at is reasonable and makes the library more useful.

@mseri
Copy link
Collaborator

mseri commented Feb 1, 2022

Thanks a lot for your patience and help!

@mseri
Copy link
Collaborator

mseri commented Feb 1, 2022

I will prepare a new release by the end of the week

@mseri mseri merged commit 9a5e683 into mirage:master Feb 1, 2022
mseri added a commit to mseri/opam-repository that referenced this pull request Feb 1, 2022
…c, rpc and ppx_deriving_rpc (8.1.2)

CHANGES:

* Add the `noargs` constructor for declaring interfaces that do not take any
  parameters. (tbrk mirage/ocaml-rpc#170)
* Allow Xmlrpc callers to override the base64 decoding function. (tbrk mirage/ocaml-rpc#171)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants