Recent

Author Topic: Same project Win8.1 vs. Win10. Encoding differences?  (Read 477 times)

Eduards

  • New Member
  • *
  • Posts: 27
Same project Win8.1 vs. Win10. Encoding differences?
« on: April 20, 2019, 03:14:23 pm »
Hello,

I have problem with different windows/lazarus versions and same project synced using dropbox.
My project uses Indy 10 to read and write Google Calendars using functions originaly written for Delphi. Maybe I should note that unit has warnings like
Code: Pascal  [Select]
  1. googlecal.pas(521,35) Warning: Implicit string type conversion with potential data loss from "WideString" to "AnsiString"
  2. googlecal.pas(522,19) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"
but they which were not causing any problems.

Step 1. I had my project build some time ago in Lazarus 1.6.2 / win 8.1 pro. It was working.
Step 2. I installed on laptop Lazarus 1.6.4 / win 10 Home. Project is synced from machine to machine using dropbox, I just rebuilt it, it was working on laptop no problem.

If I run this new executable on original desktop machine, my project asks for new google token to access Google Calendars. When I enter one, it does not accept it.
Token is saved to file on every exit.
Code: Pascal  [Select]
  1.  
  2.   Line := TStringList.Create;
  3.   Line.Add(GCalendars.RefreshToken);
  4.   Line.SaveToFile('data/google-token.ini');
Same executable asks for no tokens on laptop and just works.

So I upgraded to Lazarus 2.0 on my desktop windows 8.1 machine.  After compiling Indy twice (nothing changed there) I could build my project. Same thing continues- program asks for token, while on Win 10 laptop it works no questions asked.

I have no idea if problem is system code pages, Lazarus UFT8, line endings or I what else.

I will include whole GetTokens procedure in case that helps.
Code: Pascal  [Select]
  1. procedure TGCalendars.GetTokens;
  2.   function EncodeURL(url: string): string;
  3.   var
  4.     x: integer;
  5.     sBuff: string;
  6.   const
  7.     SafeMask = ['A'..'Z', '0'..'9', 'a'..'z', '*', '@', '.', '_', '-'];
  8.   begin
  9.     //Init
  10.     sBuff := '';
  11.  
  12.     for x := 1 to Length(url) do
  13.     begin
  14.       //Check if we have a safe char
  15.       if url[x] in SafeMask then
  16.       begin
  17.         //Append all other chars
  18.         sBuff := sBuff + url[x];
  19.       end
  20.       else if url[x] = ' ' then
  21.       begin
  22.         //Append space
  23.         sBuff := sBuff + '+';
  24.       end
  25.       else
  26.       begin
  27.         //Convert to hex
  28.         sBuff := sBuff + '%' + IntToHex(Ord(url[x]), 2);
  29.       end;
  30.     end;
  31.  
  32.     Result := sBuff;
  33.   end;
  34.  
  35. var
  36.   URLString: String;
  37.   OkResult: Boolean;
  38.   InputResult: string;
  39.   JSon: ISuperObject;
  40.   FCode: String;
  41.   Req, Resp: TStringStream;
  42. begin
  43.   FAccessToken := '';
  44.   if FRefreshToken <> '' then
  45.   begin
  46.     { Lets get access token using previous refresh token}
  47.     URLString := 'client_id=' + FClientID;
  48.     URLString := URLString + '&client_secret=' + FClientSecret;
  49.     URLString := URLString + '&refresh_token=' + FRefreshToken;
  50.     URLString := URLString + '&grant_type=refresh_token';
  51.     Req := TStringStream.Create(URLString);
  52.     Resp := TStringStream.Create('');
  53.     try
  54.       try
  55.         FHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
  56.         FHTTP.DoRequest('POST', 'https://accounts.google.com/o/oauth2/token', Req, Resp, []);
  57.  
  58.  
  59.       { When not working response was:
  60.         Recv 31.12.2017. 14:12:59: HTTP/1.1 400 Bad Request
  61.           "error" : "invalid_grant" }
  62.  
  63.       except
  64.       end;
  65.       if FHTTP.ResponseCode = 200 then
  66.       begin
  67.         JSon := SO(UTF8Decode(Resp.DataString));
  68.         FAccessToken := JSon['access_token'].AsString;
  69.         if JSon['refresh_token'] <> nil then
  70.           FRefreshToken := JSon['refresh_token'].AsString;
  71.         Exit;
  72.       end;
  73.     finally
  74.       Req.Free;
  75.       Resp.Free;
  76.     end;
  77.   end;
  78.  
  79.   { Ja kods augstāk bijis veiksmīgs, tas iziet ar Exit, un šis tālāk neizpildās.
  80.     Šeit tiek apstrādāts, ja refresh_token ir neveiksmīgs. Atveram browseri lai iegūtu "user consent" }
  81.  
  82.   URLString := 'https://accounts.google.com/o/oauth2/auth';
  83.   URLString := URLString + '?client_id=' + FClientID;
  84.   URLString := URLString + '&redirect_uri=urn:ietf:wg:oauth:2.0:oob';
  85.   URLString := URLString + '&scope=https://www.googleapis.com/auth/calendar https://www.google.com/m8/feeds';
  86.   URLString := URLString + '&response_type=code';
  87.   OpenURL(UrlString); { Lazarus equivalent of Delphi ShellExecute((Form.Handle), nil, PChar(URLString), nil, nil, 0); }
  88.  
  89.   repeat
  90.     OkResult := false;
  91.     InputResult := '';
  92.     if Assigned(FOnAuthorizationContinueQuery) then
  93.       FOnAuthorizationContinueQuery(Self, OkResult, InputResult)
  94.     else
  95.       OkResult := InputQuery(Application.Title, 'Enter your code here:', InputResult);
  96.     if OkResult then
  97.       FCode := InputResult  { that code I copy/pasted from browser }
  98.     else
  99.       Exit;
  100.  
  101.     URLString := 'client_id=' + FClientID;
  102.     URLString := URLString + '&client_secret=' + FClientSecret;
  103.     URLString := URLString + '&code=' + FCode;
  104.     URLString := URLString + '&redirect_uri=urn:ietf:wg:oauth:2.0:oob';
  105.     URLString := URLString + '&grant_type=authorization_code';
  106.     Req := TStringStream.Create(URLString);
  107.     Resp := TStringStream.Create('');
  108.     try
  109.       try
  110.         FHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
  111.         FHTTP.DoRequest('POST', 'https://accounts.google.com/o/oauth2/token', Req, Resp, []);
  112.         except
  113.       end;
  114.       if FHTTP.ResponseCode <> 200 then
  115.       begin
  116.         if Assigned(FOnWrongVerifier) then
  117.           FOnWrongVerifier(Self)
  118.         else
  119.           MessageDlg('Wrong code! Try again.', mtError, [mbOK], -1);
  120.       end
  121.       else
  122.       begin
  123.         { iegūstam gan access_token, gan refresh_token }
  124.         JSon := SO(UTF8Decode(Resp.DataString));
  125.         FAccessToken := JSon['access_token'].AsString;
  126.         if JSon['refresh_token'] <> nil then
  127.           FRefreshToken := JSon['refresh_token'].AsString;
  128.       end;
  129.     finally
  130.       Req.Free;
  131.       Resp.Free;
  132.     end;
  133.   until FHTTP.ResponseCode = 200;
  134. end;
  135.  





JimD

  • Jr. Member
  • **
  • Posts: 62
Re: Same project Win8.1 vs. Win10. Encoding differences?
« Reply #1 on: May 21, 2019, 09:10:57 pm »
Can we see the code snippet that is causing the warnings?
googlecal.pas(521,35) Warning: Implicit string type conversion with potential data loss from "WideString" to "AnsiString"
googlecal.pas(522,19) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"

Eduards

  • New Member
  • *
  • Posts: 27
Re: Same project Win8.1 vs. Win10. Encoding differences?
« Reply #2 on: July 01, 2019, 04:26:59 pm »
Here is the code. I have never worked with JSON, I use these functions and they "just work".

Code: Pascal  [Select]
  1. procedure TGEvent.SetJSON(const Value: WideString);  
  2. var
  3.   JSONDoc: ISuperObject;
  4.  
  5. begin
  6.   if FJSON <> Value then
  7.   begin
  8.     FStored := True;
  9.     FJSON := Value;
  10.     JSONDoc := SO(UTF8Decode(Value));   // Line 521
  11.     FID := JSONDoc['id'].AsString;      // Line 522
  12.     FETag := JSONDoc['etag'].AsString;
  13.     FTitle := '';
  14.  

Update. Since my original post I have upgraded all my machines to Win10. No changes. Code compiles everywhere fine, but runtime version works as intended only on initial laptop.