Changeset 42 for trunk/UContact.pas


Ignore:
Timestamp:
Dec 2, 2021, 12:18:18 PM (3 years ago)
Author:
chronos
Message:
  • Fixed: Loading of JPEG photo. Image binary data were affected by TStringList. Store them just as a string type.
  • Fixed: Reset list filter if different file is opened to avoid confusing empty list after file open.
  • Fixed: Decoding long quoted-printable text due to range check error of small index variable type.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UContact.pas

    r40 r42  
    1313  TErrorEvent = procedure (Text: string; Line: Integer) of object;
    1414
    15   TDataType = (dtString, dtInteger, dtDate, dtDateTime, dtImage);
     15  TDataType = (dtString, dtInteger, dtDate, dtDateTime, dtImage, dtStringList);
    1616
    1717  TContactFieldIndex = (cfFirstName, cfMiddleName, cfLastName, cfTitleBefore,
     
    5353
    5454  TContactProperty = class
     55  private
     56    function GetValueItem(Index: Integer): string;
     57    procedure SetValueItem(Index: Integer; AValue: string);
     58  public
    5559    Name: string;
    5660    Attributes: TStringList;
    57     Values: TStringList;
     61    Value: string;
    5862    Encoding: string;
    5963    Charset: string;
     
    6569    constructor Create;
    6670    destructor Destroy; override;
     71    property ValueItem[Index: Integer]: string read GetValueItem write SetValueItem;
    6772  end;
    6873
     
    264269{ TContactProperty }
    265270
     271function TContactProperty.GetValueItem(Index: Integer): string;
     272var
     273  List: TStringList;
     274begin
     275  List := TStringList.Create;
     276  try
     277    List.Delimiter := ';';
     278    List.NameValueSeparator := '=';
     279    List.StrictDelimiter := True;
     280    List.DelimitedText := Value;
     281    if Index < List.Count then
     282      Result := List.Strings[Index]
     283      else Result := '';
     284  finally
     285    List.Free;
     286  end;
     287end;
     288
     289procedure TContactProperty.SetValueItem(Index: Integer; AValue: string);
     290var
     291  List: TStringList;
     292begin
     293  List := TStringList.Create;
     294  try
     295    List.Delimiter := ';';
     296    List.NameValueSeparator := '=';
     297    List.StrictDelimiter := True;
     298    List.DelimitedText := Value;
     299
     300    // Extend subitems count
     301    while List.Count <= Index do
     302      List.Add('');
     303
     304    List.Strings[Index] := AValue;
     305
     306    // Remove empty items
     307    while (List.Count > 0) and (List.Strings[List.Count - 1] = '') do
     308      List.Delete(List.Count - 1);
     309
     310    Value := List.DelimitedText;
     311  finally
     312    List.Free;
     313  end;
     314end;
     315
    266316procedure TContactProperty.EvaluateAttributes;
    267317var
     
    274324    Encoding := Attributes.Values['ENCODING'];
    275325    if (Encoding = 'QUOTED-PRINTABLE') or (Encoding = 'BASE64') then begin
    276       Values.DelimitedText := GetDecodedValue;
     326      Value := GetDecodedValue;
    277327      Attributes.Delete(Attributes.IndexOfName('ENCODING'));
    278328    end;
     
    292342function TContactProperty.GetDecodedValue: string;
    293343begin
    294   if Encoding = 'BASE64' then
    295     Result := DecodeStringBase64(Values.DelimitedText)
    296   else
    297   if Encoding = 'QUOTED-PRINTABLE' then
    298     Result := DecodeQuotedPrintable(Values.DelimitedText)
     344  if Encoding = 'BASE64' then begin
     345    Result := DecodeStringBase64(Value)
     346  end else
     347  if Encoding = 'QUOTED-PRINTABLE' then begin
     348    Result := DecodeQuotedPrintable(Value)
     349  end
    299350  else Result := '';
    300351end;
     
    330381  Name := Source.Name;
    331382  Attributes.Assign(Source.Attributes);
    332   Values.Assign(Source.Values);
     383  Value := Source.Value;
     384  Encoding := Source.Encoding;
     385  Charset := Source.Charset;
    333386end;
    334387
     
    339392  Attributes.NameValueSeparator := '=';
    340393  Attributes.StrictDelimiter := True;
    341   Values := TStringList.Create;
    342   Values.Delimiter := ';';
    343   Values.NameValueSeparator := '=';
    344   Values.StrictDelimiter := True;
    345394end;
    346395
    347396destructor TContactProperty.Destroy;
    348397begin
    349   FreeAndNil(Values);
    350398  FreeAndNil(Attributes);
    351399  inherited;
     
    448496    Field := Parent.Fields.GetByIndex(Index);
    449497    if Field.ValueIndex <> -1 then begin
    450       if Field.ValueIndex < Prop.Values.Count then
    451         Result := Prop.Values.Strings[Field.ValueIndex]
    452         else Result := '';
    453     end else Result := Prop.Values.DelimitedText;
     498      Result := Prop.ValueItem[Field.ValueIndex]
     499    end else Result := Prop.Value;
    454500  end else Result := '';
    455501end;
     
    473519    if Assigned(Prop) then begin
    474520      if Field.ValueIndex <> -1 then begin
    475         // Extend subitems count
    476         while Prop.Values.Count <= Field.ValueIndex do
    477           Prop.Values.Add('');
    478 
    479         Prop.Values.Strings[Field.ValueIndex] := AValue;
    480       end else Prop.Values.DelimitedText := AValue;
    481 
    482       // Remove empty items
    483       while (Prop.Values.Count > 0) and (Prop.Values.Strings[Prop.Values.Count - 1] = '') do
    484         Prop.Values.Delete(Prop.Values.Count - 1);
     521        Prop.ValueItem[Field.ValueIndex] := AValue;
     522      end else Prop.Value := AValue;
    485523
    486524      // Remove if empty
    487       if Prop.Values.Text = '' then begin
     525      if Prop.Value = '' then begin
    488526        Properties.Remove(Prop);
    489527      end;
     
    595633    AddNew('X-TIMES_CONTACTED', [], [], STimesContacted, cfXTimesContacted, dtString);
    596634    AddNew('X-LAST_TIME_CONTACTED', [], [], SLastTimeContacted, cfXLastTimeContacted, dtString);
    597     AddNew('PHOTO', [], [], SPhoto, cfPhoto, dtString);
     635    AddNew('PHOTO', [], [], SPhoto, cfPhoto, dtImage);
    598636    AddNew('X-JABBER', [], [], SJabber, cfXJabber, dtString);
    599     AddNew('BDAY', [], [], SDayOfBirth, cfDayOfBirth, dtString);
    600     AddNew('ANNIVERSARY', [], [], SAnniversary, cfAnniversary, dtString);
     637    AddNew('BDAY', [], [], SDayOfBirth, cfDayOfBirth, dtDate);
     638    AddNew('ANNIVERSARY', [], [], SAnniversary, cfAnniversary, dtDate);
    601639    AddNew('REV', [], [], SRevision, cfRevision, dtString);
    602640    AddNew('UID', [], [], SUniqueIdentifier, cfUid, dtString);
     
    641679  I: Integer;
    642680  J: Integer;
    643   Value: string;
    644681  NameText: string;
    645682begin
     
    652689      for J := 0 to Properties.Count - 1 do
    653690      with Properties[J] do begin
    654         Value := Values.DelimitedText;
    655691        if Pos(LineEnding, Value) > 0 then begin
    656692          NameText := Name;
     
    719755            if (Length(Lines[I]) > 0) and (Lines[I][1] = ' ') then begin
    720756              Value := Value + Trim(Lines[I]);
     757            end else
     758            if (Length(Lines[I]) > 0) and (Length(Value) > 0) and (Value[Length(Value)] = '=') and
     759              (Lines[I][1] = '=') then begin
     760              Value := Value + Copy(Trim(Lines[I]), 2, MaxInt);
    721761            end else begin
    722762              Dec(I);
     
    734774            NewProperty.Attributes.Delete(0);
    735775          end;
    736           NewProperty.Values.DelimitedText := Value;
     776          NewProperty.Value := Value;
    737777          NewProperty.EvaluateAttributes;
    738778        end else Error(SFoundPropertiesBeforeBlockStart, I + 1);
Note: See TracChangeset for help on using the changeset viewer.