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

Multi vcf download plugin #12004

Merged
merged 1 commit into from
Nov 5, 2018
Merged

Multi vcf download plugin #12004

merged 1 commit into from
Nov 5, 2018

Conversation

skjnldsv
Copy link
Member

@skjnldsv skjnldsv commented Oct 24, 2018

@charismatic-claire @brjhaverkamp

This plugin allow us to POSTGET a list of vcards as a multi dimensional array and retrieve everything as a single vcf file. Needed for nextcloud/contacts#39

To discuss:

  1. shall we go with a GET instead? DONE
  2. shall we use a simple array instead of a multi dimensional one? DONE
curl 'https://dev.skjnldsv.com/remote.php/dav/addressbooks/users/admin/contacts/?export' \
	-X REPORT  --user 'admin:admin' \
	--data-binary '<x1:addressbook-multiget xmlns:x1="urn:ietf:params:xml:ns:carddav"><x0:prop xmlns:x0="DAV:"><x0:getcontenttype/><x0:getetag/><x0:resourcetype/><x0:displayname/><x0:owner/><x0:resourcetype/><x0:sync-token/><x0:current-user-privilege-set/><x0:getcontenttype/><x0:getetag/><x0:resourcetype/><x1:address-data/></x0:prop><x0:href xmlns:x0="DAV:">83F18885-8FF6-4839-9D10-C997D5BD9B96.vcf</x0:href><x0:href xmlns:x0="DAV:">470623A2-0FCB-4BA0-A6D2-6C25F4113C02.vcf</x0:href></x1:addressbook-multiget>'

apps/dav/lib/CardDAV/VCFMultiExportPlugin.php Outdated Show resolved Hide resolved
@ChristophWurst
Copy link
Member

1. shall we go with a GET instead?

If that call does not change any server state, yes.

@skjnldsv
Copy link
Member Author

skjnldsv commented Oct 24, 2018

If that call does not change any server state, yes.

Yes, I'm thinking that as well, but since muti dimentionnal arrays are terribly looking as url, I wonder if some browsers can go 💥 with that?
/remote.php/dav/addressbooks/users/admin/?vcards%5Bcontacts%5D%5B%5D=3A6B15C7-EDCF-4F14-B9DB-D427806B82A2.vcf&vcards%5Btest%5D%5B%5D=790AD673-6C80-47F9-95A7-89E9AD21B801.vcf

@rullzer
Copy link
Member

rullzer commented Oct 24, 2018

Also you hit the various browser url length limits at some point

@skjnldsv
Copy link
Member Author

Also you hit the various browser url length limits at some point

Arf, damn!
What should I do then? :(

Copy link
Member

@ChristophWurst ChristophWurst left a comment

Choose a reason for hiding this comment

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

Some general coding style feedback. Can't argue much about the logic as I'm not familiar with the details of DAV and VCF 🤷‍♂️

apps/dav/lib/CardDAV/VCFMultiExportPlugin.php Outdated Show resolved Hide resolved
apps/dav/lib/CardDAV/VCFMultiExportPlugin.php Outdated Show resolved Hide resolved

// checking that the path is a valid addressbook
if ($node instanceof AddressBook) {
$addressbooks = array_merge($addressbooks, [$addressbook => $vcards]);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
$addressbooks = array_merge($addressbooks, [$addressbook => $vcards]);
$addressbooks[$addressbook] = $vcards;

would do the exact same I guess

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually I can drop this I think now. I don't use $addressbooks anymore! 👍

@rullzer
Copy link
Member

rullzer commented Oct 24, 2018

Also you hit the various browser url length limits at some point

Arf, damn!
What should I do then? :(

Well using POST helps for that. With GET you could run into isues if people select their whole addressbook

@skjnldsv
Copy link
Member Author

skjnldsv commented Oct 24, 2018

Well using POST helps for that. With GET you could run into isues if people select their whole addressbook

Hum, no better ideas out there? Anyone?

@MorrisJobke
Copy link
Member

Hum, no better ideas out there? Anyone?

This is the only way I also have in mind :/

@ChristophWurst
Copy link
Member

Also you hit the various browser url length limits at some point

Found https://stackoverflow.com/a/2659995/2239067 and https://stackoverflow.com/a/417184/2239067 telling me the limit is at ~2KB. Based on the example URL provided I assume a typical URL parameter is up to 100 bytes longs, allowing just 20 contacts/parameters.

Since this is DAV anyway, this answer might be relevant: https://stackoverflow.com/questions/978061/http-get-with-request-body#comment10368662_978061

IMO using POST for this seems wrong as it's an idempotent operation. Still, GET is also not right, esp. with the technical limitations.

@charismatic-claire
Copy link

How about the REPORT request, that was specifically invented for that kind of a request against a CardDAV server? See Building a CardDAV client, search for the keyword "multiget".

Or is that impossible, because we are limited to GET, POST, PUT and DELETE here?

@georgehrke
Copy link
Member

@skjnldsv I don't think we need a dedicated plugin for that. You can perform a simple addressbook-multiget, put them all together into one big vcf in javascript and use a data-uri link to download.

@georgehrke
Copy link
Member

georgehrke commented Oct 25, 2018

How about the REPORT request, that was specifically invented for that kind of a request against a CardDAV server? See Building a CardDAV client, search for the keyword "multiget".

@charismatic-claire I agree that multiget is the way to go, but please take note that multiget does not return one big vcf file, but a WebDav like 207-multistatus response with individual vcfs. See https://tools.ietf.org/html/rfc6352#section-8.7.1 :)

@skjnldsv
Copy link
Member Author

@georgehrke @charismatic-claire
So I would then build the vcf in the browser?
That's something I really don't like. If I have a selection of 1000 vcfs, I want to just trigger a download. Any javascript computation will explode the browser, especially if the vcfs are big :(

@charismatic-claire
Copy link

@skjnldsv
I think the whole point of building that plugin server side was to not let the browser do the heavy lifting. But I see your point. If the Contacts app fires a multiget request via REPORT and receives lots of single VCFs as a response, it will have to do exactly that... Hm... Can't our plugin just return one single VCF as a result? But that would be against the standard, right? Hm... So the question becomes: Is there a standard for our use case, or do we have to invent one? And if so, is that a good idea? Do I miss something here?

@georgehrke
Copy link
Member

Well, you could adapt the VCFExportPlugin to allow appending ?export to the url when sending REPORT requests.

@skjnldsv
Copy link
Member Author

skjnldsv commented Oct 25, 2018

Well, you could adapt the VCFExportPlugin to allow appending ?export to the url when sending REPORT requests.

then build a blob from the report request and trigger a redirect to the blob?
Could be clean yes!!

@charismatic-claire you're right on the point yes!
Thank you both!! I will adapt this later.

@charismatic-claire could you then adapt this behavior to the contacts app? :)
https://www.npmjs.com/package/file-saver

@charismatic-claire
Copy link

@skjnldsv I'll be glad to help :-)

@skjnldsv skjnldsv force-pushed the dl-vcf-groups-plugin branch from 5f2b244 to 5387c87 Compare October 25, 2018 16:53
@skjnldsv
Copy link
Member Author

@georgehrke done! :)
Should you implement this into the cdavlib then?

@skjnldsv
Copy link
Member Author

@MorrisJobke @rullzer @ChristophWurst a little review for the php?

@ChristophWurst
Copy link
Member

Is this plugin even needed now? The discussion above – esp #12004 (comment) and #12004 (comment) – tells me this might not be required if I understand correctly.

@skjnldsv
Copy link
Member Author

@ChristophWurst I updated the plugin to use the multi-get like @georgehrke said :)

If you do a multiget with ?export at the end, it will return a vcf file and not a dav response ;)

curl 'https://dev.skjnldsv.com/remote.php/dav/addressbooks/users/admin/contacts/?export' \
	-X REPORT  --user 'admin:admin' \
	--data-binary '<x1:addressbook-multiget xmlns:x1="urn:ietf:params:xml:ns:carddav"><x0:prop xmlns:x0="DAV:"><x0:getcontenttype/><x0:getetag/><x0:resourcetype/><x0:displayname/><x0:owner/><x0:resourcetype/><x0:sync-token/><x0:current-user-privilege-set/><x0:getcontenttype/><x0:getetag/><x0:resourcetype/><x1:address-data/></x0:prop><x0:href xmlns:x0="DAV:">83F18885-8FF6-4839-9D10-C997D5BD9B96.vcf</x0:href><x0:href xmlns:x0="DAV:">470623A2-0FCB-4BA0-A6D2-6C25F4113C02.vcf</x0:href></x1:addressbook-multiget>'

@charismatic-claire
Copy link

@ChristophWurst Maybe every pull request should start with a comprehensive description of the "ticket" we are trying to solve here. I'll try to briefly summarize what we wanted to achieve:

  • In the Contacts app, we want to add the possibility to export whole groups of contacts. Say you have 5 address books and 10 groups. What you might want is to export all members from all address books belonging to a certain group. Or maybe you want to search for a certain phrase and want to export all contacts matching that search. Or you want to manually select a number of contacts you want to export.
  • By "export" in mean you want to download one single vcf file containing all the vCards of all the contacts you want to export.
  • Here is what we wanna do: To achieve this, the interface of the Contacts app shall compile a REPORT request for all the wanted contacts. If you send this to the CardDAV server, it will respond with a list of all the contacts. So the transformation into one single vcf file which could be downloaded would be done on the browser side via JavaScript. This is what @skjnldsv wants to avoid here.
  • That's why we need this plugin here. With a export parameter appended to the URL of the REPORT request, this plugin would transform this response into one single vcf file.
  • See Currently not possible to download group of contacts for more

Does that make clear what we want and why we need this plugin on the server side? Feel free to ask, if not :-)

@skjnldsv skjnldsv added the high label Nov 3, 2018
Copy link
Member

@georgehrke georgehrke left a comment

Choose a reason for hiding this comment

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

And please squash all commits :)

apps/dav/lib/CardDAV/MultiGetExportPlugin.php Outdated Show resolved Hide resolved
apps/dav/lib/CardDAV/MultiGetExportPlugin.php Outdated Show resolved Hide resolved
Signed-off-by: John Molakvoæ (skjnldsv) <[email protected]>
@ChristophWurst
Copy link
Member

Thank you, @charismatic-claire ✌️

@skjnldsv skjnldsv requested a review from georgehrke November 5, 2018 07:53
Copy link
Member

@ChristophWurst ChristophWurst left a comment

Choose a reason for hiding this comment

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

Fine, I guess 🐘

@skjnldsv skjnldsv added 4. to release Ready to be released and/or waiting for tests to finish and removed 3. to review Waiting for reviews labels Nov 5, 2018
@skjnldsv
Copy link
Member Author

skjnldsv commented Nov 5, 2018

Failure unrelated

@skjnldsv skjnldsv merged commit 934d08b into master Nov 5, 2018
@skjnldsv skjnldsv deleted the dl-vcf-groups-plugin branch November 5, 2018 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4. to release Ready to be released and/or waiting for tests to finish enhancement feature: dav high
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants