transmission-remote-gui / transgui

🧲 A feature rich cross platform Transmission BitTorrent client. Faster and has more functionality than the built-in web GUI.
GNU General Public License v2.0
3.23k stars 280 forks source link

Don't use integers in place of booleans in RPC #1467

Closed lighterowl closed 7 months ago

lighterowl commented 7 months ago

A lot of places in transgui use integers in RPC requests where the daemon expects booleans.

A recent commit in Transmission started actually enforcing this as the JSON parsing implementation has changed.

Originally reported in https://github.com/xavery/transgui/issues/79 and cherry-picked from https://github.com/xavery/transgui/commit/409512f85001d0865dba2a21ce1497b2c60c0d8d.

what-the-diff[bot] commented 7 months ago

PR Summary

These enhancements aim to enforce better user interface management, limiting potential mishaps caused by accidental multiple clicks, as well as ensuring a smoother user experience during the testing process.

ghost commented 7 months ago
👇 Click on the image for a new way to code review #### [![Review these changes using an interactive CodeSee Map](https://s3.us-east-2.amazonaws.com/maps.codesee.io/images/github/transmission-remote-gui/transgui/1467/1aa79e57/041aa08a178ddab26a6f649f4e286db30f27aac6.svg)](https://app.codesee.io/r/reviews?pr=1467&src=https%3A%2F%2Fgithub.com%2Ftransmission-remote-gui%2Ftransgui) #### Legend CodeSee Map legend
fredo-47 commented 7 months ago

I can confirm that transgui is broken when used with newer transmission-daemon dev-versions, regarding functions "Move torrent data" and "Delete torrent data".

After I built transgui with the file changes suggested above, transgui is able to perform these functions again as expected.

PeterDaveHello commented 7 months ago

@fredo-47 Thanks for the contribution. I will take my spare time to review them as soon as possible.

killemov commented 7 months ago

A bot wrote:

It's generally a good practice to add comments explaining the purpose of the code, especially when making changes. Consider adding a comment near this code block explaining the purpose of the condition and what it checks for.

Too bad the bot does not warn against over-commenting, so much comments that important stuff gets lost or comments that state the obvious. Only if requesting the field from the request argument had some unforeseen side-effect, a comment about that would be valid otherwise the code itself is clear enough.

killemov commented 7 months ago

Can anyone tell me if the used JSON parser can handle truthy and falsy values correctly?

lighterowl commented 7 months ago

Can anyone tell me if the used JSON parser can handle truthy and falsy values correctly?

It's not that simple to determine because you need to explicitly state the type you're accessing when fetching values from a parsed object. However, when you access Booleans, it seems to kind-of-sort-of have the "truthy-falsy" behaviour. Have a look yourself :

unit TestCase1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, fpcunit, testregistry, fpjson, jsonparser;

type

  JsonTruthyFalsy= class(TTestCase)
  published
    procedure BoolAsInteger;
    procedure StringboolAsInteger;
    procedure StringboolAsBool;
    procedure StringAsBool;
    procedure IntegerAsBool;
  end;

implementation

procedure JsonTruthyFalsy.BoolAsInteger;
var
  obj : TJSONObject;
begin
  obj := GetJSON('{"foobar":true}') as TJSONObject;
  AssertEquals(obj.Integers['foobar'], 1);
end;

procedure JsonTruthyFalsy.StringboolAsInteger;
var
  obj : TJSONObject;
begin
  obj := GetJSON('{"foobar":"true"}') as TJSONObject;
  AssertEquals(obj.Integers['foobar'], 1);
end;

procedure JsonTruthyFalsy.StringboolAsBool;
var
  obj : TJSONObject;
begin
  obj := GetJSON('{"foobar":"true"}') as TJSONObject;
  AssertTrue(obj.Booleans['foobar']);
end;

procedure JsonTruthyFalsy.StringAsBool;
var
  obj : TJSONObject;
begin
  obj := GetJSON('{"foobar":"transgui"}') as TJSONObject;
  AssertTrue(obj.Booleans['foobar']);
end;

procedure JsonTruthyFalsy.IntegerAsBool;
var
  obj : TJSONObject;
begin
  obj := GetJSON('{"foobar":1}') as TJSONObject;
  AssertTrue(obj.Booleans['foobar']);
end;

initialization
  RegisterTest(JsonTruthyFalsy);
end.

Out of those, StringboolAsInteger and StringAsBool fail.

This means that "true" and 1 are converted to true when using .Booleans.

killemov commented 7 months ago

Good, this means the original Integer "getter" and comparison to 0 were actually bad programming and that it's fixed even if the actual values in the JSON are 0 or 1.