Changeset 59 for trunk/UContact.pas


Ignore:
Timestamp:
Dec 8, 2021, 11:33:52 PM (3 years ago)
Author:
chronos
Message:
  • Added: Support for GIF images for contact photo.
  • Fixed: Saving multi-line values.
  • Fixed: Escaping combined values with backslash symbol.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UContact.pas

    r58 r59  
    169169resourcestring
    170170  SVCardFile = 'vCard file';
    171   SFoundPropertiesBeforeBlockStart = 'Found properties before the start of block';
    172   SFoundBlockEndWithoutBlockStart = 'Found block end without block start';
    173171  SExpectedVCardBegin = 'Expected vCard begin';
    174172  SFieldIndexNotDefined = 'Field index not defined';
     
    279277end;
    280278
     279function EndsWith(Text, What: string): Boolean;
     280begin
     281  Result := Copy(Text, Length(Text) - Length(What) + 1, MaxInt) = What;
     282  if Result then begin
     283    Result := Result;
     284  end;
     285end;
     286
     287function EncodeEscaped(Text: string): string;
     288var
     289  I: Integer;
     290begin
     291  Result := '';
     292  I := 1;
     293  while I <= Length(Text) do begin
     294    if Text[I] in [',', '\', ';'] then Result := Result + '\' + Text[I]
     295      else Result := Result + Text[I];
     296    Inc(I);
     297  end;
     298end;
     299
     300function DecodeEscaped(Text: string): string;
     301var
     302  I: Integer;
     303  Escaped: Boolean;
     304begin
     305  Result := '';
     306  I := 1;
     307  Escaped := False;
     308  while I <= Length(Text) do begin
     309    if Escaped then begin
     310      Result := Result + Text[I];
     311      Escaped := False;
     312    end else begin
     313      if Text[I] = '\' then begin
     314        Escaped := True;
     315      end else Result := Result + Text[I];
     316    end;
     317    Inc(I);
     318  end;
     319end;
     320
    281321{ TContactField }
    282322
     
    342382begin
    343383  I := 0;
    344   while (I < Count) and (Items[I].Name <> Name) do Inc(I);
     384  while (I < Count) and (Items[I].Name <> Name) and (not EndsWith(Items[I].Name, '.' + Name)) do Inc(I);
    345385  if I < Count then Result := Items[I]
    346386    else Result := nil;
     
    473513  I: Integer;
    474514begin
    475   Result := Name = AName;
     515  Result := (Name = AName) or EndsWith(Name, '.' + AName);
    476516  if Result and (Length(Groups) > 0) then begin
    477517    for I := 0 to Length(Groups) - 1 do
     
    639679      Field := Parent.Fields.GetByIndex(Index);
    640680      if Field.ValueIndex <> -1 then begin
    641         Result := Prop.ValueItem[Field.ValueIndex]
     681        Result := DecodeEscaped(Prop.ValueItem[Field.ValueIndex])
    642682      end else Result := Prop.Value;
    643683    end else Result := '';
     
    664704    if Assigned(Prop) then begin
    665705      if Field.ValueIndex <> -1 then begin
    666         Prop.ValueItem[Field.ValueIndex] := AValue;
     706        Prop.ValueItem[Field.ValueIndex] := EncodeEscaped(AValue);
    667707      end else Prop.Value := AValue;
    668708
     
    747787  OutText: string;
    748788  LinePrefix: string;
     789  CutLength: Integer;
    749790const
    750791  MaxLineLength = 73;
     
    774815          while True do begin
    775816            if Length(OutText) > MaxLineLength then begin
    776               if (LineIndex > 0) and (LinePrefix = '') then LinePrefix := ' ';
    777               Add(LinePrefix + Copy(OutText, 1, MaxLineLength));
    778               System.Delete(OutText, 1, MaxLineLength);
     817              CutLength := MaxLineLength;
     818              if Encoding = 'QUOTED-PRINTABLE' then begin
     819                // Do not cut encoded items
     820                if ((CutLength - 2) >= 1) and (OutText[CutLength - 2] = '=') then
     821                  Dec(CutLength, 2)
     822                else if ((CutLength - 1) >= 1) and (OutText[CutLength - 1] = '=') then
     823                  Dec(CutLength, 1);
     824              end;
     825              Add(LinePrefix + Copy(OutText, 1, CutLength));
     826              LinePrefix := ' ';
     827              System.Delete(OutText, 1, CutLength);
    779828              Inc(LineIndex);
    780829              Continue;
     
    852901          NewProperty.Attributes.Delete(0);
    853902        end;
    854         NewProperty.Value := Value;
     903        NewProperty.Value := DecodeEscaped(Value);
    855904        NewProperty.EvaluateAttributes;
    856905      end else begin
     
    881930var
    882931  Lines: TStringList;
    883   I: Integer;
    884932begin
    885933  Lines := TStringList.Create;
     
    892940      end;
    893941    end;
    894     I := LoadFromStrings(Lines);
     942    LoadFromStrings(Lines);
    895943  finally
    896944    Lines.Free;
     
    10531101  Contact: TContact;
    10541102  I: Integer;
     1103  NewI: Integer;
    10551104begin
    10561105  inherited;
     
    10691118      Contact := TContact.Create;
    10701119      Contact.Parent := Self;
    1071       I := Contact.LoadFromStrings(Lines, I);
    1072       if (I <= Lines.Count) and (I <> -1) then Contacts.Add(Contact)
    1073       else begin
     1120      NewI := Contact.LoadFromStrings(Lines, I);
     1121      if NewI <= Lines.Count then begin
     1122        if NewI <> -1 then begin
     1123          Contacts.Add(Contact);
     1124          I := NewI;
     1125        end else begin
     1126          FreeAndNil(Contact);
     1127          Inc(I);
     1128        end;
     1129      end else begin
    10741130        FreeAndNil(Contact);
    10751131        Break;
Note: See TracChangeset for help on using the changeset viewer.