nextcloud / contacts

📇 Contacts app for Nextcloud
https://apps.nextcloud.com/apps/contacts
GNU Affero General Public License v3.0
565 stars 171 forks source link

Contact has 161 MB because of (automated) social media avatar #2743

Open dschrempf opened 2 years ago

dschrempf commented 2 years ago

Describe the bug

I noticed out of memory errors on my phone related to DavX5 synchronization (Nextcloud <-> Android). After digging around for a few hours, I saw that one of my Nextcloud contacts has 161MB because of an avatar that was downloaded automatically. The VCF file shows

PHOTO;ENCODING=B;TYPE=PNG;VALUE=BINARY:iVBORw0KGgoAAAANSUhEUgAAAtAAAALQCAYA
 AAC5V0ecAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAgAElEQVR42sy92ZIkObIldhSAmW+RGblU1n

and then endless lines of photo data.

Has this been an issue for other users? Did you already encounter such a problem?

Thanks for looking into this!

Steps to reproduce

I didn't do anything special. Just added the contact a while ago. (Email, and name).

Expected behavior

Avatars are small.

Actual behavior

Avatar has 161MB.

Contact version

No response

Operating system

No response

PHP engine version

No response

Web server

No response

Database

No response

Operating system

No response

List of activated Apps

Contacts.

Nextcloud Signing status

No response

Configuration report

No response

Additional info

No response

call-me-matt commented 2 years ago

Oh wow - 161 MB! :scream: Can you check if there are multiple PHOTO-tags for the contact? Maybe there is a bug which is adding pictures instead of replacing them? And can you cross check the size of the avatar which was downloaded on the respective social network? Is it also that big?

dschrempf commented 2 years ago

Of course I was intelligent enough to delete this contact :(, but I checked on other contacts with pictures (those are smaller, around 5 to 10MB). And yes, already in the first contact I found two PHOTO; tags.

About the social network type. I am not sure how the download works. The only thing I provided for the 161MB contact is a Gmail address. When I click on the contact picture, I have "Get from Gravatar".

dschrempf commented 2 years ago

I should say that this contact was the first on the "All contacts" list with a social media profile picture. Maybe the social media scraper was going down the list and always adding another avatar to this first contact before failing. Because all other contacts wiht social media pictures were much smaller (5-10MB).

call-me-matt commented 2 years ago

So every time you download a new gravatar picture for your contact, a picture is added and not replaced for that person? Can you try the following?

  1. create a new contact
  2. add an email address that uses gravatar
  3. click on the profile picture and select "download from gravatar"
  4. wait for the green confirmation info
  5. change the email address to another one that uses gravatar
  6. click once more on the profile picture and select "download from gravatar"
  7. wait for the green confirmation info
  8. download the contact and check there is only one PHOTO tag

For me, using contacts 4.0.1 there is never more than one PHOTO tag. What version of the contacts-App do you use? If you can, please check in the database which VCARD version number the broken contacts have.

tcitworld commented 2 years ago

We'll need a repair step in server too

dschrempf commented 2 years ago

Thanks for looking into this, and sorry for the late reply.

I followed the steps of @call-me-matt and indeed, only one PHOTO tag is in the contact file, even when changing the email address. When trying to download the avatar a second time, a toast informs me about the avatar already being up to date. So the problem happened already some time ago. This particular avatar that caused a contact to have 161MB has around 1MB, so it was downloaded 150 times in the course of the last months, I guess :-).

call-me-matt commented 2 years ago

When trying to download the avatar a second time, a toast informs me about the avatar already being up to date.

Just to be sure, when changing the address a new photo should be downloaded, the picture should not be up to date anymore and a green toast should state a successful download. And then, still only one photo tag should be attached to the contacts VCF fille because hopefully the picture has been updated, not added.

dschrempf commented 2 years ago

Yes, this was the case!

RokeJulianLockhart commented 2 years ago

Is your desire for all contact-avatars to be lossilly compressed? I desire the opposite, because if my contacts are to contain avatars, I want them to be of the best resolution that is possible. This problem is primarily the fault of the database that is unable to store that picture.

tcitworld commented 2 years ago

For now we don't compress pictures, just resizing them to 256x256 maximum (keeping ratio), since most contact apps won't make use of higher sizes. If the aim is to use very large contacts pictures, vcard supports putting an URI to a direct picture instead of inserting the data inline, though I do not know if any CardDAV compatible app supports doing that. In the long-term, Nextcloud could support saving contacts pictures in appdata (publicly accessible) files instead of into the database.

dschrempf commented 2 years ago

I don't have any opinion about that. I think this issue is more about duplicate PHOTO tags, and I think it has been solved already. Is this the case? What has not been solved is: Maybe others were also (unknowingly) hit by this problem, and then the server has to repair duplicate tags.

craig-st commented 2 years ago

I encountered the same problem. @dschrempf described "out of memory errors on my phone related to DavX5 synchronization." I, too, have that problem. It results in an oom kill (Out Of Memory) event on the phone.

In addition, I encountered problems in the the nextcloud web interface in a browser. The web interface spins, spins, spins and then shows something like "No contacts yet. Would you like to create a contact?" In other words, cannot access ANY contacts in the nextcloud web interface because of one faulty vcard / contact.

On the server side, apache2 error log has:

[Sat Jul 16 20:31:36.437988 2022] [proxy_fcgi:error] [pid 210:tid 139802190681856] [client 192.168.1.11:45762] AH01071: Got error 'PHP message: PHP Fatal error: Allowed memory size of 1342177280 bytes exhausted (tried to allocate 4096 bytes) in /srv/www/nextcloud-23.0.6/apps/dav/lib/CardDAV/CardDavBackend.php on line 975'

The specific value of "Allowed memory size" shown above depends on the php config setting for memory_limit. In my case, memory_limit = 1024M. When I change to memory_limit = -1, the server php script consumes over 4GB of server memory before finally completing. Crazy.

If you have a lot of contacts, just finding the faulty vcard(s) / contact(s) is challenging. I have about 2,500 contacts. I used the following postgresql SQL query to find the problematic vcards / contacts. Maybe there's a better way: postgres=# SELECT id, addressbookid, uri, lastmodified, etag, size, uid FROM oc_cards ORDER BY size DESC LIMIT 10;

From the results of the above SQL query, grab the value of "id". Let's say its "1234". Use that as "cardid" in the following SQL query: postgres=# select * from oc_cards_properties where cardid='1234';

The result should give you the information you need to track down the faulty vcard / contact using the nextcloud web interface. One can then save / download / export the faulty vcard / contact to a local file before deleting it from the nextcloud server using the nextcloud web interface. You may need to repeat this process for multiple faulty vcards / contacts.

Some observations that may or may not be relevant:

Looking at the 'lastmodified' tag, it seems the problem did not happen as soon as the image was added. By "added" I mean when it was retrieved from social media. Days (maybe a week or two?) went by after the image was added before getting oom (out of memory) errors. Is there some sort of faulty lazy post-processing that happens? But I could be wrong.

The faulty image is a PNG. Most images are JPG and are not a problem. Again, not sure if this is relevant or a red herring.

The PHOTO tag is slightly different. For the faulty vcard, the photo tag is

PHOTO;ENCODING=B;TYPE=PNG;VALUE=BINARY:

A non-faulty vcard has this:

PHOTO;ENCODING=b;TYPE=JPEG:

I'm just wondering what the "VALUE=BINARY" is all about. My knowledge of vcard tag syntax is zero, so may be totally irrelevant.

But what definitely is relevant and is a problem is the number of times the PHOTO tag (and its encoded data) appears in the faulty vcard. Once I found the offending faulty vcard / contact using the SQL queries outlined above, and set php config memory_limit = -1 so that the nextcloud web interface would load, I was able to find and to save / download / export the faulty vcard / contact to a vcf file using the nextcloud web interface in a browser. The downloaded vcf file -- containing one, single, faulty contact -- is 322 MB, and the PHOTO tag (with its encoded data) repeats 323 times.

pongraczi commented 1 year ago

Hi, I just experienced the same with the recent version of Nextcloud.
Contacts 5.3.2

I downloaded one vcard, it contains 45 pictures, all the same, all of them: PHOTO;ENCODING=b;TYPE=JPEG;VALUE=BINARY

My questions:

RokeJulianLockhart commented 1 year ago

@pongraczi, that's probably best asked on the forum, I think, since you're asking about sanitizing an export of the database rather than trying to fix the database importing images.

call-me-matt commented 1 year ago

In case there is a follow up in the forum, I am interested and would be happy if you could post the link here. I did not manage to reproduce, all my contacts have only one picture. and even when duplicating a photo in a vcard manually and importing it to Nextcloud, it results in one (broken) image only. PS: does the contact auto-repair if you update the picture once more?

pongraczi commented 1 year ago

@pongraczi, that's probably best asked on the forum, I think, since you're asking about sanitizing an export of the database rather than trying to fix the database importing images.

My bad, I used wrong words, sorry.

tcitworld commented 1 year ago

Unfortunately that's not easily possible. We'll need a repair step in server as said before. https://github.com/nextcloud/contacts/issues/2743#issuecomment-1128481030

call-me-matt commented 1 year ago

I finally found a contact with the same behavior and took a look

VERSION:3.0
PRODID;VALUE=TEXT:-//Sabre//Sabre VObject 4.1.2//EN

while my other contacts are

VERSION:4.0
PRODID:+//IDN bitfire.at//DAVx5/4.2.6-ose ez-vcard/0.11.3

Note: These values are from the oc_cards table. When downloading the contacts via the web frontend, the 4.0 contact is retrieved as

VERSION:3.0
PRODID:-//Sabre//Sabre VObject 4.4.2//EN

I tried to fix the broken 3.0 contact, but did not manage to. Here is what I tried:

So my conclusion is that there must be a bug in the update-picture routine for v3.0 cards (the one for social updates, but also the one for manual image uploads).

How to reproduce with manual image uploads:

  1. find v3.0 VCARDs: SELECT addressbookid,uid from oc_cards WHERE carddata LIKE '%VERSION:3%' ORDER BY addressbookid;
  2. open one of these contacts in the web gui
  3. edit the contact and remove all pictures
  4. add one picture, then another
  5. download the vcard from the web gui
  6. notice that there are now empty PHOTO: entries, one for each image update and the social update of the avatar picture is not working for that contact any more