~mil/sxmo-devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
1

[PATCH peanutbutter] Add parameter to set touch grid resolution.

Details
Message ID
<20241202113709.1288535-2-proycon@anaproy.nl>
DKIM signature
pass
Download raw message
Patch: +100 -72
A higher resolution increases the number of passcode permutations.
Resolution can be set from 1 (1x1 = 1 quadrant, touch anywhere to
unlock, insecure) to 4 (4x4 = 16
quadrants). The default remains 2x2 = 4 quadrants.

Quadrants are numbered horizontal-first, starting from 1. Except for resolution
4, where they start from 0 and are counted in hexademical up to f. Each
character in a passcode corresponds to a quadrant. Passcodes can have
arbitrary length (like before). See the README for further explanation.
---
This patch should again be applied on top of my previous peanutbutter patches.

 Cargo.lock        |   2 +-
 Cargo.toml        |   2 +-
 README.md         |  28 +++++++++--
 src/main.rs       |  16 ++++++
 src/touch_pass.rs | 124 ++++++++++++++++++++++------------------------
 5 files changed, 100 insertions(+), 72 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index a247b2b..6bf5783 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -455,7 +455,7 @@ dependencies = [

[[package]]
name = "peanutbutter"
version = "0.4.1"
version = "0.5.0"
dependencies = [
 "cairo-rs",
 "chrono",
diff --git a/Cargo.toml b/Cargo.toml
index f75dc1a..d732892 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "peanutbutter"
version = "0.4.1"
version = "0.5.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/README.md b/README.md
index 9993fea..dfd527f 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ When peanutbutter crashes, ssh into your phone and check the `/tmp/peanutbutter.

# Controls

The screen is segregated into 4 corners:
By default, the screen is segregated into 4 quadrants (resolution 2):

1. Top left
2. Top right
@@ -89,7 +89,29 @@ mistake, simply start tapping the sequence anew.

A touch will be acknowledged by flipping the background, this provides only
provides a indication whether the touch was registered, not whether it is a
valid touch in the passcode sequence.
valid touch in the passcode sequence. The feedback will be over the entire screen
and will not specifically highlight the quadrant you tapped (as a security measure).
Visual feedback can be disabled entirely by passing the `-F` or `--nofeedback` option.

Another way to increase security, is to set the parameter `-3` to change the
resolution to 3 (3x3 = 9 quadrants). Which takes the following configuration:

```
1 2 3 
4 5 6
7 8 9
```

You can even go up to `-4`, which will give you this next configuration (4x4 =
16 quadrants):

```
0 1 2 3 
4 5 6 7
8 9 a b
c d e f
```


# Safety

@@ -101,6 +123,4 @@ Try `pkill peanutbutter`.

FAQ: https://lists.sr.ht/~anjan/public-inbox/%3CD08OUBZEXWSQ.3M648R47PDJC1@matfyz.cz%3E#%3CD2UYYQ6C2LQG.1KYZEAJ0X2Z2N@momi.ca%3E

- Clean up code (compiler warnings)
- Package
- Show an incoming call and pickup easily via lock screen
diff --git a/src/main.rs b/src/main.rs
index 5bc7994..8a08f79 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -22,6 +22,7 @@ fn main() {
    let mut nofeedback = false;
    let mut statuscommand: Option<Vec<String>> = None;
    let mut parsefont = false;
    let mut resolution = 2;
    let mut fontname: String = "Sans".into();
    for argument in env::args().skip(1) {
        match argument.as_str() {
@@ -30,6 +31,10 @@ fn main() {
            "-F" | "--nofeedback" => nofeedback = true,
            "-s" | "--statuscommand" => statuscommand = Some(Vec::new()),
            "-f" | "--font" => parsefont = true,
            "-1" => resolution = 1,
            "-2" => resolution = 2,
            "-3" => resolution = 3,
            "-4" => resolution = 4,
            "-h" | "--help" => {
                eprintln!("Options:");
                eprintln!(
@@ -39,6 +44,16 @@ fn main() {
                eprintln!(" -F / --nofeedback               Disable touch feedback");
                eprintln!(" -f / --font [font               Set font family");
                eprintln!(" -s / --statuscommand [command]  Run this command for a status line, it should run continuously and each new output line will become the status line");
                eprintln!(" -1                              1x1 touch grid (insecure)");
                eprintln!(
                    " -2                              2x2 touch grid (1=topleft, 4=bottomright)"
                );
                eprintln!(
                    " -3                              3x3 touch grid (1=topleft, 9=bottomright)"
                );
                eprintln!(
                    " -4                              4x4 touch grid (0=topleft, f=bottomright)"
                );
                std::process::exit(0);
            }
            "-v" | "--version" => {
@@ -117,6 +132,7 @@ fn main() {
        way_state.width.unwrap(),
        way_state.height.unwrap(),
        passcode.as_deref(),
        resolution,
    ));

    //single blocking dispatch before the main loop
diff --git a/src/touch_pass.rs b/src/touch_pass.rs
index e951def..e07c318 100644
--- a/src/touch_pass.rs
+++ b/src/touch_pass.rs
@@ -1,105 +1,97 @@
use std::collections::VecDeque;
use std::fmt;

//in numeric representation (quadrants): 1132
const DEFAULT_PASSCODE: [PasscodeItem; 4] = [
    PasscodeItem::TopLeft,
    PasscodeItem::TopLeft,
    PasscodeItem::BottomLeft,
    PasscodeItem::TopRight,
];
//in numeric representation (quadrants): 1132 , with 4 quadrants this corresponds to topleft, topright, bottomleft, bottomright
const DEFAULT_PASSCODE: [u8; 4] = [1, 1, 3, 2];

#[derive(Copy, Clone, PartialEq, Debug)]
enum PasscodeItem {
    TopLeft,
    TopRight,
    BottomLeft,
    BottomRight,
}

impl TryFrom<char> for PasscodeItem {
    type Error = &'static str;
    fn try_from(value: char) -> Result<Self, Self::Error> {
        match value {
            '1' => Ok(PasscodeItem::TopLeft),
            '2' => Ok(PasscodeItem::TopRight),
            '3' => Ok(PasscodeItem::BottomLeft),
            '4' => Ok(PasscodeItem::BottomRight),
            _ => Err("invalid quadrant for passcodeitem: use 1 (topleft), 2 (topright), 3 (bottomleft) ,4 (bottomright)")
        }
    }
}

impl fmt::Display for PasscodeItem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            PasscodeItem::TopLeft => write!(f, "TOP LEFT"),
            PasscodeItem::TopRight => write!(f, "TOP RIGHT"),
            PasscodeItem::BottomLeft => write!(f, "BOTTOM LEFT"),
            PasscodeItem::BottomRight => write!(f, "BOTTOM RIGHT"),
fn read_passcode_char(value: char, resolution: u8) -> Result<u8, &'static str> {
    match value {
        '0' if resolution == 4 => Ok(0),
        '1' => Ok(1),
        '2' if resolution >= 2 => Ok(2),
        '3' if resolution >= 2 => Ok(3),
        '4' if resolution >= 2 => Ok(4),
        '5' if resolution >= 3 => Ok(5),
        '6' if resolution >= 3 => Ok(6),
        '7' if resolution >= 3 => Ok(7),
        '8' if resolution >= 3 => Ok(8),
        '9' if resolution >= 3 => Ok(9),
        'A' | 'a' if resolution == 4 => Ok(10),
        'B' | 'b' if resolution == 4 => Ok(11),
        'C' | 'c' if resolution == 4 => Ok(12),
        'D' | 'd' if resolution == 4 => Ok(13),
        'E' | 'e' if resolution == 4 => Ok(14),
        'F' | 'f' if resolution == 4 => Ok(15),
        _ => {
            if resolution == 2 {
                Err("invalid quadrant for passcodeitem: 1 (topleft), 2 (topright), 3 (bottomleft), 4 (bottomright)")
            } else if resolution == 3 {
                Err("invalid quadrant for passcodeitem: use 1 (topleft),2,3 (topright),4,5 (center),6,7 (bottomleft),8,9 (bottomright)")
            } else if resolution == 4 {
                Err("invalid quadrant for passcodeitem: use 0 (topleft),1,2,3(topright),4,5,6,7,8,9,a,b,c (bottomleft),d,e,f (bottomright)")
            } else {
                Err("invalid quadrant for passcodeitem")
            }
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct TouchState {
    passcode: Vec<PasscodeItem>,
    touches: VecDeque<PasscodeItem>,
    passcode: Vec<u8>,
    touches: VecDeque<u8>,
    resolution: u8,
    max_touches: usize,
    half_width: f64,
    half_height: f64,
    grid_width: f64,
    grid_height: f64,
}

impl TouchState {
    pub fn new(width: i32, height: i32, passcode: Option<&str>) -> Self {
    pub fn new(width: i32, height: i32, passcode: Option<&str>, resolution: u8) -> Self {
        if resolution < 1 || resolution > 4 {
            panic!("Invalid resolution");
        }
        Self {
            passcode: if let Some(passcode) = passcode {
                passcode
                    .chars()
                    .map(|x| x.try_into().expect("Invalid passcode"))
                    .map(|x| read_passcode_char(x, resolution).expect("Invalid passcode"))
                    .collect()
            } else if resolution == 1 {
                vec![1]
            } else {
                DEFAULT_PASSCODE.iter().copied().collect()
            },
            touches: VecDeque::new(),
            resolution,
            max_touches: if let Some(passcode) = passcode {
                passcode.chars().count()
            } else if resolution == 1 {
                1
            } else {
                DEFAULT_PASSCODE.len()
            },
            half_width: width as f64 / 2.0,
            half_height: height as f64 / 2.0,
            grid_width: width as f64 / (resolution as f64),
            grid_height: height as f64 / (resolution as f64),
        }
    }

    pub fn resize(&mut self, width: i32, height: i32) {
        self.half_width = width as f64 / 2.0;
        self.half_height = height as f64 / 2.0;
        self.grid_width = width as f64 / (self.resolution as f64);
        self.grid_height = height as f64 / (self.resolution as f64);
    }

    pub fn add_touch(&mut self, x_val: f64, y_val: f64) -> bool {
        let touch: Option<PasscodeItem> = if x_val < self.half_width && y_val < self.half_height {
            Some(PasscodeItem::TopLeft)
        } else if x_val > self.half_width && y_val < self.half_height {
            Some(PasscodeItem::TopRight)
        } else if x_val < self.half_width && y_val > self.half_height {
            Some(PasscodeItem::BottomLeft)
        } else if x_val > self.half_width && y_val > self.half_height {
            Some(PasscodeItem::BottomRight)
        } else {
            None
        };
        let startindex: u8 = if self.resolution == 4 { 0 } else { 1 };

        if let Some(touch) = touch {
            self.touches.push_back(touch);
            while self.touches.len() > self.max_touches {
                self.touches.pop_front();
            }
            true
        } else {
            eprintln!("unknown touch!");
            false
        let x = (x_val / self.grid_width).floor() as u8;
        let y = (y_val / self.grid_height).floor() as u8;
        let code = y * self.resolution + x + startindex;

        self.touches.push_back(code);
        while self.touches.len() > self.max_touches {
            self.touches.pop_front();
        }
        true
    }

    pub fn is_pass_valid(&self) -> bool {
-- 
2.47.1
Details
Message ID
<D64F810SSB35.1P792IRAXZZAT@momi.ca>
In-Reply-To
<20241202113709.1288535-2-proycon@anaproy.nl> (view parent)
DKIM signature
pass
Download raw message
Thanks!

To git@git.sr.ht:~anjan/peanutbutter
   f02fa612..3d78f0e2  master -> master
Reply to thread Export thread (mbox)