Hi all, Is there a way in vpim to edit an individual field in a vcard. I have a set of vcards stored in a db and would like to be able to edit individual fields in the vcard and then save the vcard back to the db. I didn''t see any methods for editing a vcard in the api. Do I need to create a new vcard and repopulate it with all the fields except the one that I''m changing and then push the new value? thanks, AF -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/vpim-talk/attachments/20060224/2832bff4/attachment.htm
Quoting aidanf at gmail.com, on Fri, Feb 24, 2006 at 02:32:45PM +0000:> Is there a way in vpim to edit an individual field in a vcard. I have a set > of vcards stored in a db and would like to be able to edit individual fields > in the vcard and then save the vcard back to the db. I didn''t see any > methods for editing a vcard in the api. Do I need to create a new vcard and > repopulate it with all the fields except the one that I''m changing and then > push the new value?Currently, yes. Use Vpim::Maker::Vcard.make(), then call maker#add_field for every field you want to add unchanged. For the field you want to change, call Vpim::DirectoryInfo::Field#copy to get a mutable version of the field, mutate it (#value=, etc.), then add it. What I was worried about was that people would change a card to no longer be valid, remove VERSION:, add a second N:, etc. So, I wanted it to be hard to damage a vCard that you had decoded. If you want to change it, just make another. This seems a little painful as I describe it, though, and maybe I should give developers enough rope to hang themselves. Or, I might add a maker#copy(other_card) API, that copies all the fields in the other_card into the one being made (if its valid, no duplicate VERSION, etc.). Maybe I could also make it take an optional block. I would yield the field to the block, and if the block returns true, copy it, or even add the return value of the yield, but its not so different from doing it yourself: other_card.each do |field| if want to change it.. field = field.copy field.value= ''other'' end maker.add_field(field) end What do you think? Cheers, Sam
Hi Sam, Thanks for your reply. I think it would be useful to be able to edit a vcard in place rather than having to copy all the fields into a new vcard. I wouldn''t worry about the user nuking their vcards - I think it should be up to the user to make sure the edited vcard is valid. I think you can already mess up a vcard anyway by using push to append a field to a vcard if that field already exists. Another issue related to editing is the ability to save a vcard in different formats. For example, if I edit a vcard that is vcard-2.1, vpim will save the new vcard as vcard-3.0 format. It would be useful to be able to specify vcard2.1 format, or have a method for outputing the vcard as a string in 2.1 format. Cheers, AF On 2/25/06, Sam Roberts <sroberts at uniserve.com> wrote:> > > Currently, yes. > > Use Vpim::Maker::Vcard.make(), then call maker#add_field for every field > you want to add unchanged. For the field you want to change, call > Vpim::DirectoryInfo::Field#copy to get a mutable version of the field, > mutate it (#value=, etc.), then add it. > > What I was worried about was that people would change a card to no > longer be valid, remove VERSION:, add a second N:, etc. So, I wanted it > to be hard to damage a vCard that you had decoded. If you want to change > it, just make another. > > This seems a little painful as I describe it, though, and maybe I should > give developers enough rope to hang themselves. > > Or, I might add a maker#copy(other_card) API, that copies all the fields > in the other_card into the one being made (if its valid, no duplicate > VERSION, etc.). Maybe I could also make it take an optional block. I > would yield the field to the block, and if the block returns true, copy > it, or even add the return value of the yield, but its not so different > from doing it yourself: > > other_card.each do |field| > if want to change it.. > field = field.copy > field.value= ''other'' > end > maker.add_field(field) > end > > What do you think? > > Cheers, > Sam > > > > _______________________________________________ > Vpim-talk mailing list > Vpim-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/vpim-talk >-- ------------------------------- http://www.aidanf.net ------------------------------- -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/vpim-talk/attachments/20060301/3e520f95/attachment.htm
> Thanks for your reply. I think it would be useful to be able to edit a vcard > in place rather than having to copy all the fields into a new vcard. I > wouldn''t worry about the user nuking their vcards - I think it should be up > to the user to make sure the edited vcard is valid. I think you can already > mess up a vcard anyway by using push to append a field to a vcard if that > field already exists.True, though I''ve called that a bug and fixed it in my working copy (can''t add BEGIN/END/VERSION, can''t add N or FN if they are already there, everything else is allowed multiples). I also added copying examples, and higher level APIs to copy kindof based on what I described below. I''ve some more hours of work before its cleaned up for release, though, the unit tests are broken. And I''ll try and come up with an API to make Vcard mutable in some way that is moderately safe. It won''t be in the next release, though, I''ve a day job. :-)> Another issue related to editing is the ability to save a vcard in > different formats. For example, if I edit a vcard that is vcard-2.1, > vpim will save the new vcard as vcard-3.0 format. It would be useful > to be able to specify vcard2.1 format, or have a method for outputing > the vcard as a string in 2.1 format.One of the design goals of vPim is to NOT modify input data if possible when rewriting, so this is definitely a problem. I''ll also try and make round-trip work 1-to-1, and make it faster (profiling makes it look like performance is dominated by String#upcase and String#downcase, believe it or not). The encoding variables are: - VCARD version (2.1/3.0), which mostly affects how params are specified, and the allowed encodings and names of those encodings. - character set Currently, decoding auto detects utf-8 and ucs-2, with or without byte order marks, but always writes as utf-8 without BOM. It would be nice to control this. I''ve two possible approaches: - make these options part of the Vcard, so changing the version would involve mutating the vCard or copying a vCard to a new one that is set to a different version - make them an input to the encoding process, where the default is the values stored in Vcard when it was decoded. Have you ever wanted to encode the same card in multiple character sets, or multiple vCard versions? If that is common, I need to make it part of the encoding process, otherwise I can make it part of the Vcard, which is easier Cheers, Sam
Hi Sam, I have never wanted to encode a vcard in multiple versions or multiple character sets. It might be useful to explain what I''m using vpim for. I''m using vpim to read and edit my phone contacts. Currently I''m using php to do this but am changing to vpim as I''ve started using ruby a lot in the last couple of months. The idea is that I can sync my phone contacts to my computer, edit them there and then sync them back to the phone. This requires the ability to save the vcard back in the same format and character set as it was originally encoded (Most mobile phones implement vcard2.1, but not 3.0.) What encodings are currently supported by vpim? I tested vpim with a couple of thousand vcards and 12 failed to decode with Vpim::InvalidEncodingError. Cheers, AF> The encoding variables are: > - VCARD version (2.1/3.0), which mostly affects how params are > specified, and the allowed encodings and names of those encodings. > - character set > > Currently, decoding auto detects utf-8 and ucs-2, with or without byte > order marks, but always writes as utf-8 without BOM. It would be nice to > control this. > > I''ve two possible approaches: > > - make these options part of the Vcard, so changing the version would > involve mutating the vCard or copying a vCard to a new one that is > set to a different version > > - make them an input to the encoding process, where the default is the > values stored in Vcard when it was decoded. > > Have you ever wanted to encode the same card in multiple character sets, > or multiple vCard versions? If that is common, I need to make it part of > the encoding process, otherwise I can make it part of the Vcard, which > is easier-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/vpim-talk/attachments/20060303/d4a9e001/attachment-0001.htm
Quoting aidanf at gmail.com, on Fri, Mar 03, 2006 at 12:25:24PM +0000:> I have never wanted to encode a vcard in multiple versions or multiple > character sets. > > The idea is that I can sync my phone contacts to my computer, edit them > there and then sync them back to the phone. This requires the ability to > save the vcard back in the same format and character set as it was > originally encoded (Most mobile phones implement vcard2.1, but not 3.0.)So you don''t want transcoding, but you want encoding preserved. Ok, thats not so hard to do. Much easier than transcoding.> What encodings are currently supported by vpim? I tested vpim with a couple > of thousand vcards and 12 failed to decode with Vpim::InvalidEncodingError.Thats great that you could do that. I would like to see the ones that failed, I think I support any valid 2.1 vCard, but I could be wrong, or the card could be technically invalid. Even if they are invalid, I want vPim to be useful, not righteous, so I would try and make decoding work. On encoding, I just reemit the fields, in their original forms. The only things that might cause you problems are new fields that use base64 encoding, and (as you found), that new cards always use version 3.0. I can add support for encoding version 2.1 cards. - can you give me examples of cards that fail? - what kinds of fields do you add? - what kinds of fields to you delete, if any? - do you ever modify fields? - what kinds of character set are these cards encoded in? have you had any problems with how vpim treats character sets? - what php vcard lib did you use? did you like its api? Btw, The biggest difference between 2.1 and 3.0 is the types of encodings supported, 3.0 just allows encoding=b (base-64), version 2.1 allows encoding=7bit, 8bit, quoted-printable, and base64. Unless you have pictures, certs, or other binary data in your cards, that shouldn''t matter. The other difference is that 2.1 allows params to miss their name, you can write: ADR;home:blah,blah,... And the decoder is supposed to realize that means ADR;type=home:blah,blah,... but if you see a raw "base64", the decoder is supposed to realize that what is meant is encoding=base64. Anyhow, I support this on input, but don''t encode things like that. The fully specified pname=pvalue is always allowed by 2.1 and 3.0. Cheers, Sam
I will send you some examples of vcards that fail. Most of the failed ones had notes or labels of ENCODING=QUOTED-PRINTABLE that caused the decoding exception. I mostly add/delete/edit name and telephone fields but have the ability to add/delete/edit all the defined fields. At the moment I am doing this by creating a contact object with attr_accessor methods for all the vcard fields and using vpim to load these values from a vcard and save them back to a vcard. cheers, AF On 3/4/06, Sam Roberts <sroberts at uniserve.com> wrote:> > Quoting aidanf at gmail.com, on Fri, Mar 03, 2006 at 12:25:24PM +0000: > > I have never wanted to encode a vcard in multiple versions or multiple > > character sets. > > > > The idea is that I can sync my phone contacts to my computer, edit them > > there and then sync them back to the phone. This requires the ability to > > save the vcard back in the same format and character set as it was > > originally encoded (Most mobile phones implement vcard2.1, but not 3.0.) > > So you don''t want transcoding, but you want encoding preserved. Ok, > thats not so hard to do. Much easier than transcoding. > > > What encodings are currently supported by vpim? I tested vpim with a > couple > > of thousand vcards and 12 failed to decode with > Vpim::InvalidEncodingError. > > Thats great that you could do that. I would like to see the ones that > failed, I think I support any valid 2.1 vCard, but I could be wrong, or > the card could be technically invalid. Even if they are invalid, I want > vPim to be useful, not righteous, so I would try and make decoding work. > > On encoding, I just reemit the fields, in their original forms. The only > things that might cause you problems are new fields that use base64 > encoding, and (as you found), that new cards always use version 3.0. I > can add support for encoding version 2.1 cards. > > - can you give me examples of cards that fail? > - what kinds of fields do you add? > - what kinds of fields to you delete, if any? > - do you ever modify fields? > - what kinds of character set are these cards encoded in? have you had > any problems with how vpim treats character sets? > - what php vcard lib did you use? did you like its api? > > Btw, The biggest difference between 2.1 and 3.0 is the types of > encodings supported, 3.0 just allows encoding=b (base-64), version 2.1 > allows encoding=7bit, 8bit, quoted-printable, and base64. Unless you > have pictures, certs, or other binary data in your cards, that shouldn''t > matter. > > The other difference is that 2.1 allows params to miss their name, you > can write: > > ADR;home:blah,blah,... > > And the decoder is supposed to realize that means > > ADR;type=home:blah,blah,... > > but if you see a raw "base64", the decoder is supposed to realize that > what is meant is encoding=base64. Anyhow, I support this on input, but > don''t encode things like that. The fully specified pname=pvalue is > always allowed by 2.1 and 3.0. > > Cheers, > Sam > >-- ------------------------------- http://www.aidanf.net ------------------------------- -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/vpim-talk/attachments/20060308/ae1c2a51/attachment.htm
Sam Roberts
2006-Mar-09 05:27 UTC
[Vpim-talk] possibly invalid quoted printable in v2.1 vcards
Quoting aidanf at gmail.com, on Wed, Mar 08, 2006 at 11:25:22AM +0000:> Hi Sam, > Here are some examples of vcards that failed to decode. I tested vpim > against a database of contacts from the place where I work. From around 4800 > contacts, only 12 failed. I''ve tried to anonymize them a bit by just > replacing names and phonenumbers.Can you confirm this is really what the cards look like: BEGIN:VCARD VERSION:2.1 N:Middle Family;Ny_full LABEL;CHARSET=ISO-8859-1;ENCODING=QUOTED-PRINTABLE:Box 1234=0AWorkv=E4gen 2=0AWorkv=E4gen 1=0AUme=E5=0AV=E4sterbotten=0A12345=0AS END:VCARD If so, I''m not sure what I can do. Thats not a valid 2.1 vCard as far as I can tell. I keep staring and staring at the spec from imc.org, and its not formatted like any of the examples in the spec. The text is so vague, its hard to say definitively that its wrong, but I don''t think it is folded properly, it should look like: BEGIN:VCARD VERSION:2.1 N:Middle Family;Ny_full LABEL;CHARSET=ISO-8859-1;ENCODING=QUOTED-PRINTABLE:Box 1234=0AWorkv=E4gen 2=0AWorkv=E4gen 1=0AUme=E5=0AV=E4sterbotten=0A12345=0AS END:VCARD See the space at the beginning? That''s how you know the next line is a continuation of the previous LABEL: line. Also, the trailing "=" must be removed, too. I''m sorry, I would have to gut the decoder and the internal APIs to deal with this, and unless I find out that this kind of encoding is pretty common, thats not what I want to spend my time doing. I''ve hacked the decoder to support other invalid encodings, but those were easy, this would be pretty time consuming. If you want to do it, I''m happy give you pointers on how to write a vCard 2.0 decoding routine that deals with this, the core Field.decode0() routine would be usable. Pre-processing your input with the following filter will allow you to read the cards in: qp = false $stdin.each do |line| if line =~ /;ENCODING=QUOTED-PRINTABLE[:;].*=$/ qp = true line.gsub!(/=$/, '''') elsif qp $stdout << '' '' if line =~ /=$/ # qp continues line.gsub!(/=$/, '''') else qp = false end end $stdout << line # When we see the beginning of if line =~ /;ENCODING=QUOTED-PRINTABLE[:;].*=$/ end end If the phone is just echoing back what it was given, you might be able to just patch the cards, and maybe the corrected ones can be downloaded and retrieved, and all will be well from now on. If the phone itself is doing this kind of quoted-printable, and requires that format, then you might have to post-process to reverse the process above. Btw, all the cards failed for the same reason. Sorry. Sam
Aidan Finn
2006-Mar-13 23:46 UTC
[Vpim-talk] possibly invalid quoted printable in v2.1 vcards
Yup, I checked and thats what the vcards actually look like, even if they''re not following the spec. I''ll wait and see how common this problem is (<0.25%in my test) before I look at implementing a decoder for it. For the moment it looks a lot easier to just preprocess the input and then write back a valid vcard. Cheers, AF On 3/9/06, Sam Roberts <sroberts at uniserve.com> wrote:> > Quoting aidanf at gmail.com, on Wed, Mar 08, 2006 at 11:25:22AM +0000: > > Hi Sam, > > Here are some examples of vcards that failed to decode. I tested vpim > > against a database of contacts from the place where I work. From around > 4800 > > contacts, only 12 failed. I''ve tried to anonymize them a bit by just > > replacing names and phonenumbers. > > Can you confirm this is really what the cards look like: > > BEGIN:VCARD > VERSION:2.1 > N:Middle Family;Ny_full > LABEL;CHARSET=ISO-8859-1;ENCODING=QUOTED-PRINTABLE:Box 1234=0AWorkv=E4gen > > 2=0AWorkv=E4gen 1=0AUme=E5=0AV=E4sterbotten=0A12345=0AS > END:VCARD > > If so, I''m not sure what I can do. Thats not a valid 2.1 vCard as far as > I can tell. I keep staring and staring at the spec from imc.org, and its > not formatted like any of the examples in the spec. The text is so > vague, its hard to say definitively that its wrong, but I don''t think it > is folded properly, it should look like: > > BEGIN:VCARD > VERSION:2.1 > N:Middle Family;Ny_full > LABEL;CHARSET=ISO-8859-1;ENCODING=QUOTED-PRINTABLE:Box 1234=0AWorkv=E4gen > 2=0AWorkv=E4gen 1=0AUme=E5=0AV=E4sterbotten=0A12345=0AS > END:VCARD > > See the space at the beginning? That''s how you know the next line is a > continuation of the previous LABEL: line. Also, the trailing "=" must be > removed, too. > > I''m sorry, I would have to gut the decoder and the internal APIs to deal > with this, and unless I find out that this kind of encoding is pretty > common, thats not what I want to spend my time doing. I''ve hacked the > decoder to support other invalid encodings, but those were easy, this > would be pretty time consuming. > > If you want to do it, I''m happy give you pointers on how to write a > vCard 2.0 decoding routine that deals with this, the core > Field.decode0() routine would be usable. > > Pre-processing your input with the following filter will allow you to > read the cards in: > > qp = false > > $stdin.each do |line| > if line =~ /;ENCODING=QUOTED-PRINTABLE[:;].*=$/ > qp = true > line.gsub!(/=$/, '''') > elsif qp > $stdout << '' '' > if line =~ /=$/ > # qp continues > line.gsub!(/=$/, '''') > else > qp = false > end > end > > $stdout << line > > # When we see the beginning of > if line =~ /;ENCODING=QUOTED-PRINTABLE[:;].*=$/ > end > end > > If the phone is just echoing back what it was given, you might be able > to just patch the cards, and maybe the corrected ones can be downloaded > and retrieved, and all will be well from now on. If the phone itself is > doing this kind of quoted-printable, and requires that format, then you > might have to post-process to reverse the process above. > > Btw, all the cards failed for the same reason. > > Sorry. > Sam > > > >-- ------------------------------- http://www.aidanf.net ------------------------------- -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/vpim-talk/attachments/20060313/e31040bb/attachment-0001.htm