Blog

  • get-shit-done

    Get shit done

    This browser extension will “block” some specific sites by turning them to a black background with 👁️ (Yes, I am watching you 🙂).

    Features

    • Currently support sites: Facebook, Messenger, TikTok
    • Can manage specific sites to block in manifest.json, using match patterns
    • Can block sites in specific time ranges, or block forever (can be unblocked by turning off the extension permanently temporarily)
    • Can display your favorite motivational quotes
    • And more, if you know JavaScript, there are lots of things you can do with this extension 😉

    Todo/Idea

    • Redirect to specific website if blocking
    • Convert to userscripts, make it easier to manage for different sites
    • Only allow limit time for each site, using cookie to store time spent

    How to use

    1. Clone this repository/download zip and extract to a folder on your local machine.
    git clone --depth 1 https://github.com/ngntrgduc/get-shit-done.git
    
    1. Load extension:
    • Chrome:  Settings -> Extensions.
    • Edge:  Extensions -> Manage Extensions.

    Then turn on Developer mode. Finally, click Load unpacked and select the folder you have just cloned/downloaded.

    Contributing

    If you found a bug or want to contribute, feel free to open a issue/pull requests. All contributions are welcomed.

    Coffee

    If you like this project and want to support me, you can buy me a coffee ☕.

    Visit original content creator repository
    https://github.com/ngntrgduc/get-shit-done

  • mldonkey

    MLDonkey: cross-platform multi-network peer-to-peer daemon

    Build

    A lot of documentation (wiki) and user forums were previously hosted at http://mldonkey.sourceforge.net, but were shut down on August 21, 2023, see issue #90 for the details and links to the data dumps (help needed to restore them to the usable form).

    GitHub Discussions serves as a replacement for the forum for the time being.

    Build

    Supported OCaml versions are >= 4.03 and < 5.0, see mldonkey.opam for canonical information.

    GTK2 GUI (./configure --enable-gui=newgui2) builds only in specific configuration when lablgtk2 packages are installed in $(ocamlc -where)/lablgtk2. This happens to be true on Debian when building with packaged (system) ocaml :

    sudo apt install ocaml camlp4 libnum-ocaml-dev liblablgtk2-gnome-ocaml-dev
    

    It is known to not work with opam – this is the goal for the next release (only gui is affected, core itself builds fine in opam).

    ./configure --enable-batch --enable-gui=newgui2 (ie download and build lablgtk2 locally) only works with old OCaml versions (e.g. 4.05.0) because it is using very old lablgtk2. Upgrading to the newer lablgtk2 is the goal for the next release

    Visit original content creator repository https://github.com/ygrek/mldonkey
  • happyFeat

    HappyFeat – Interactive framework for clinical BCI applications

    docs status test: status PyPI version License: BSD-3

    HappyFeat is a software aiming to to simplify the use of BCI pipelines in clinical settings. More precisely, it is a software assitant for extracting and selecting classification features for BCI.

    Get started!

    It gathers all necessary manipulations and analysis in a single convenient GUI, and automates experimental or analytic parameters. The resulting workflow allows for effortlessly selecting the best features, helping to achieve good BCI performance in time-constrained environments. Alternative features based on Functional Connectivity can be used and compared or combined with Power Spectral Density, allowing a network-oriented approach.

    It consists of Qt-based GUIs and Python toolboxes, allowing to realize all steps for customizing and fine-tuning a BCI system: feature extraction & selection, classifier training.

    HappyFeat also allows to interface with BCI softwares (OpenViBE for the moment!) in order to facilitate the whole BCI workflow, from data acquisition to online classification.

    The focus is put on ease of use, trial-and-error training of the classifier, and fast and efficient analysis of features of interest from BCI sessions.

    Key Features

    • Easy to use GUI allowing to extract and visualize classification features, and select the most relevant ones for training a classifier.
    • Use Spectral Power or Coherence-based features for classification. HappyFeat allows to extract & visualize both types of features in parallel, and mix them at the training level.
    • Feature selection and classifier training can be done multiple times in a row, until satisfactory results are achieved.
    • A worspace management system keeps tracks of all extraction- and training-related manipulations, and enables a high degree of reproducibility.

    Requirements

    Installation & Full documentation

    HappyFeat is available as a package on PyPi. Otherwise, you can clone this repository.

    Go to https://happyfeat.readthedocs.io/en/latest/ for more details.

    License

    This software is licensed using BSD 3-Clause. Please refer to LICENSE.md for more details.

    Visit original content creator repository https://github.com/Inria-NERV/happyFeat
  • stairsJs

    Introduction

    StairsJs is a minimal NodeJS app to automatically drive the stairs LED lights using 2 passive infra red detectors (PIRs) and uses the current sunset and sunrise times to activate the stair LED lights when someone enters the PIR detection zone. It can run by it own (after installation no internet required). It uses 3rd party packages for logging (bunyan), determination of sunset and sunrise (suncalc) and of course a package for the input and output GPIO (onoff).

    Purpose

    The goal of this project is to build a nice led-light for my stairs (which I renovated recently) and to learn the raspberry PI, nodeJS and GPIO programming

    Hardware and Electric Scheme

    List of each component with a link to specification and a global schematic overview with the list of used pin’s of the raspberry PI can be found on the wiki page

    Pictures

    stairs board

    Installation notes

    Prerequisites: You need node and npm installed on your RPI system. You can check if you have it installed in a terminal window with:

    node -v
    npm -v

    To install node + npm execute:

    curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
    sudo apt-get install -y nodejs

    See also w3schools for more details to install raspbian and node.

    Installation steps:

    1. Fork this package to your github account and/or

    2. Clone it from github to your server

    git clone https://github.com/[your-account-name-here]/stairsJs.git
    1. Install its dependencies
    npm install
    

    NOTE: Use npm install –only=production to install only dependencies, and not devDependencies,regardless of the value of the NODE_ENV environment variable.

    1. Run the program

    use one of the following commands

    node stairsJs
    
    npm start

    or use PM2 (auto starts / auto restart the program after boot)

    pm2 start stairsJs.js

    For the last option you need to install PM2

    1. Execute the unit- and integration tests (todo)
    gulp test
    

    Contribute

    Report a bug or a suggestion by posting an issue on the git repository (https://github.com/Vinz68/stairsJs/issues).

    TODO List:

    • include code quality check (JSLint or something else..)
    • create a GUI client to show status and gain control of the stairs logic, using web-technology. This is currently under development, see stairsJs-control-panel

    If you used this to build your own stairs-led-light then send me a picture ; love to see it !.

    Visit original content creator repository https://github.com/Vinz68/stairsJs
  • car-rental

    Car Rental System

    This repository contains the code for a simple car rental system implemented in Java. It includes several Java classes that work together to manage car rentals, customers, and rental records.

    Table of Contents

    Car.java

    The Car.java file contains the class definition for the Car object. This class represents a car that can be rented in the system. It includes properties such as the car’s make, model, year, and rental status. It also provides methods to get and set these properties.

    Main.java

    The Main.java file contains the main entry point for the car rental system. It provides a simple command-line interface for users to interact with the system. Users can perform actions such as renting a car, returning a car, and viewing rental records.

    Person.java

    The Person.java file contains the class definition for the Person object. This class represents a person who can rent a car in the system. It includes properties such as the person’s name, contact information, and rental history. It also provides methods to get and set these properties.

    Rent.java

    The Rent.java file contains the class definition for the Rent object. This class represents a car rental transaction in the system. It includes properties such as the rented car, the renting person, and the rental duration. It also provides methods to get and set these properties.

    RentRecord.java

    The RentRecord.java file contains the class definition for the RentRecord object. This class represents a record of a car rental in the system. It includes properties such as the rental ID, the rented car, the renting person, the rental start date, and the rental end date. It also provides methods to get and set these properties.

    Contributing

    If you would like to contribute to this project, you can follow these steps:

    1. Fork the repository on GitHub.
    2. Clone the forked repository to your local machine.
    3. Create a new branch for your changes.
    4. Make your modifications or add new features.
    5. Test your changes to ensure they work correctly.
    6. Commit your changes and push them to your forked repository.
    7. Submit a pull request to the original repository, describing your changes in detail.

    Please make sure to adhere to the existing coding style and conventions used in the project. Also, ensure that your changes are well-documented and accompanied by appropriate test cases.

    We appreciate any contributions, including bug fixes, new features, and improvements to the existing codebase.

    Contact

    If you have any questions or suggestions regarding this project, you can contact the project maintainers at johnrhuell@gmail.com.

    Thank you for your interest in this car rental system!

    Visit original content creator repository
    https://github.com/VSUrhuel/car-rental

  • classified

    classified

    A simpler NixOS secrets management system.

    Problem

    There’re some secrets management systems for NixOS (agenix, sops-nix), but they require kinda complicated setup. In many cases it’s enough to just decrypt all the secrets with root-readable key file present on disk (if someone has root access to your computer, you’re probably already royally fucked).

    Solution

    Use a simple encryption program and put the config into a NixOS module. Just like this:

    # flake.nix
    {
      inputs = {
        classified = {
          url = "github:GoldsteinE/classified";
          # to avoid having one more copy of nixpkgs
          inputs.nixpkgs.follows = "nixpkgs";
          # you can also do this with naersk
        };
      };
      outputs = { nixpkgs, classified, ... }: {
        nixosConfigurations.your-hostname = nixpkgs.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = [
            # other modules here
            ./configuration.nix
            classified.nixosModules."${system}".default
          ];
        };
      };
    }

    and then

    # configuration.nix
    {
     classified = {
       # Default is `/var/secrets`.
       # Note that this should be an empty directory:
       # while the service is running, all the files in that directory
       # will be masked by the tmpfs mount and not accessible.
       targetDir = "/var/classfied";
       keys = {
         first = "/path/to/first.key";
         second = "/path/to/second.key";
       };
       files = {
         top-secret = {
           # You can omit the `key` attribute if you have exactly one key configured
           key = "first";
           encrypted = ./encrypted-file;
           # Default is `400`
           mode = "440";
           # Defaults are `root:root`
           user = "nginx";
           group = "nogroup";
         };
       };
     };
    }

    Generating keys and encrypting data

    # (as root)
    umask 377  # so the key file has the right permissions
    classified gen-key > /path/to/key
    cat /path/to/key  # key is just 24 words, so you can write it down
    umask 022  # it's ok for encrypted data to be world-readable
    classified encrypt --key /path/to/key /path/to/secret-data > /path/to/encrypted-data
    # if you ever want to manually decrypt it
    classified decrypt --key /path/to/key /path/to/encrypted-data

    What’s inside?

    • XChaCha20-Poly1305 which is proven secure. The nonce is chosen randomly for every encrypted file.

    • A fresh tmpfs is created on every decryption, so old secrets are not available.

    • No temporary files are written, no Rust unsafe code is used, and the codebase is small and easy to audit yourself.

    • It attempts to zeroize any keys and decrypted files before deallocating memory.

    So it’s secure?

    I mean…

    • It didn’t pass any kind of professional security review.

    • Zeroizing memory is hard and should be considered best-effort.

    So (as with any cryptography project) — use at your own risk.

    Visit original content creator repository
    https://github.com/GoldsteinE/classified

  • stats-base-dmidrange

    About stdlib…

    We believe in a future in which the web is a preferred environment for numerical computation. To help realize this future, we’ve built stdlib. stdlib is a standard library, with an emphasis on numerical and scientific computation, written in JavaScript (and C) for execution in browsers and in Node.js.

    The library is fully decomposable, being architected in such a way that you can swap out and mix and match APIs and functionality to cater to your exact preferences and use cases.

    When you use stdlib, you can be absolutely certain that you are using the most thorough, rigorous, well-written, studied, documented, tested, measured, and high-quality code out there.

    To join us in bringing numerical computing to the web, get started by checking us out on GitHub, and please consider financially supporting stdlib. We greatly appreciate your continued support!

    dmidrange

    NPM version Build Status Coverage Status

    Calculate the mid-range of a double-precision floating-point strided array.

    The mid-range, or mid-extreme, is the arithmetic mean of the maximum and minimum values in a data set. The measure is the midpoint of the range and a measure of central tendency.

    Installation

    npm install @stdlib/stats-base-dmidrange

    Alternatively,

    • To load the package in a website via a script tag without installation and bundlers, use the ES Module available on the esm branch (see README).
    • If you are using Deno, visit the deno branch (see README for usage intructions).
    • For use in Observable, or in browser/node environments, use the Universal Module Definition (UMD) build available on the umd branch (see README).

    The branches.md file summarizes the available branches and displays a diagram illustrating their relationships.

    To view installation and usage instructions specific to each branch build, be sure to explicitly navigate to the respective README files on each branch, as linked to above.

    Usage

    var dmidrange = require( '@stdlib/stats-base-dmidrange' );

    dmidrange( N, x, strideX )

    Computes the mid-range of a double-precision floating-point strided array x.

    var Float64Array = require( '@stdlib/array-float64' );
    
    var x = new Float64Array( [ 1.0, -2.0, 2.0 ] );
    
    var v = dmidrange( x.length, x, 1 );
    // returns 0.0

    The function has the following parameters:

    • N: number of indexed elements.
    • x: input Float64Array.
    • strideX: stride length for x.

    The N and stride parameters determine which elements in the strided array are accessed at runtime. For example, to compute the mid-range of every other element in x,

    var Float64Array = require( '@stdlib/array-float64' );
    
    var x = new Float64Array( [ 1.0, 2.0, 2.0, -7.0, -2.0, 3.0, 4.0, 2.0 ] );
    
    var v = dmidrange( 4, x, 2 );
    // returns 1.0

    Note that indexing is relative to the first index. To introduce an offset, use typed array views.

    var Float64Array = require( '@stdlib/array-float64' );
    
    var x0 = new Float64Array( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ] );
    var x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
    
    var v = dmidrange( 4, x1, 2 );
    // returns 1.0

    dmidrange.ndarray( N, x, strideX, offsetX )

    Computes the mid-range of a double-precision floating-point strided array using alternative indexing semantics.

    var Float64Array = require( '@stdlib/array-float64' );
    
    var x = new Float64Array( [ 1.0, -2.0, 2.0 ] );
    
    var v = dmidrange.ndarray( x.length, x, 1, 0 );
    // returns 0.0

    The function has the following additional parameters:

    • offsetX: starting index for x.

    While typed array views mandate a view offset based on the underlying buffer, the offset parameter supports indexing semantics based on a starting index. For example, to calculate the mid-range for every other element in x starting from the second element

    var Float64Array = require( '@stdlib/array-float64' );
    
    var x = new Float64Array( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ] );
    
    var v = dmidrange.ndarray( 4, x, 2, 1 );
    // returns 1.0

    Notes

    • If N <= 0, both functions return NaN.

    Examples

    var discreteUniform = require( '@stdlib/random-array-discrete-uniform' );
    var dmidrange = require( '@stdlib/stats-base-dmidrange' );
    
    var x = discreteUniform( 10, -50, 50, {
        'dtype': 'float64'
    });
    console.log( x );
    
    var v = dmidrange( x.length, x, 1 );
    console.log( v );

    C APIs

    Usage

    #include "stdlib/stats/base/dmidrange.h"

    stdlib_strided_dmidrange( N, *X, strideX )

    Computes the mid-range of a double-precision floating-point strided array x.

    const double x[] = { 1.0, 2.0, 3.0, 4.0 };
    
    double v = stdlib_strided_dmidrange( 4, x, 1 );
    // returns 2.5

    The function accepts the following arguments:

    • N: [in] CBLAS_INT number of indexed elements.
    • X: [in] double* input array.
    • strideX: [in] CBLAS_INT stride length for X.
    double stdlib_strided_dmidrange( const CBLAS_INT N, const double *X, const CBLAS_INT strideX );

    stdlib_strided_dmidrange_ndarray( N, *X, strideX, offsetX )

    Computes the mid-range of a double-precision floating-point strided array using alternative indexing semantics.

    const double x[] = { 1.0, 2.0, 3.0, 4.0 };
    
    double v = stdlib_strided_dmidrange_ndarray( 4, x, 1, 0 );
    // returns 2.5

    The function accepts the following arguments:

    • N: [in] CBLAS_INT number of indexed elements.
    • X: [in] double* input array.
    • strideX: [in] CBLAS_INT stride length for X.
    • offsetX: [in] CBLAS_INT starting index for X.
    double stdlib_strided_dmidrange_ndarray( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX );

    Examples

    #include "stdlib/stats/base/dmidrange.h"
    #include <stdio.h>
    
    int main( void ) {
        // Create a strided array:
        const double x[] = { 1.0, -2.0, -3.0, 4.0, -5.0, -6.0, 7.0, 8.0 };
    
        // Specify the number of elements:
        const int N = 4;
    
        // Specify the stride length:
        const int strideX = 2;
    
        // Compute the mid-range:
        double v = stdlib_strided_dmidrange( N, x, strideX );
    
        // Print the result:
        printf( "mid-range: %lf\n", v );
    }

    See Also


    Notice

    This package is part of stdlib, a standard library for JavaScript and Node.js, with an emphasis on numerical and scientific computing. The library provides a collection of robust, high performance libraries for mathematics, statistics, streams, utilities, and more.

    For more information on the project, filing bug reports and feature requests, and guidance on how to develop stdlib, see the main project repository.

    Community

    Chat


    License

    See LICENSE.

    Copyright

    Copyright © 2016-2025. The Stdlib Authors.

    Visit original content creator repository https://github.com/stdlib-js/stats-base-dmidrange
  • Inspector

    🕵🏽‍♂️ Inspector

    Inspector is a debugging library written in Swift.

    Header Demo GIF

    Contents


    Requirements

    • iOS 11+
    • Xcode 13+
    • Swift 5.4+

    Why use it?

    Improve development experience

    • Add your own custom commands to the main Inspector interface and make use of key commands while using the Simulator.app (and also on iPad).
    • Create layer views by any criteria you choose to help you visualize application state: class, a property, anything.
    • Inspect view hierarchy faster then using Xcode’s built-in one, or
    • Inspect view hierarchy without Xcode.
    • Test changes and fix views live.

    Improve QA and Designer feedback with a reverse Zeplin

    • Inspect view hierarchy without Xcode.
    • Test changes and fix views live.
    • Easily validate specific state behaviors.
    • Better understanding of the inner-workings of components
    • Give more accurate feedback for developers.

    Installation

    Swift Package Manager

    The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler. It is in early development, but Inspector does support its use on supported platforms.

    Once you have your Swift package set up, adding Inspector as a dependency is as easy as adding it to the dependencies value of your Package.swift.

    // Add to Package.swift
    
    // For projects with iOS 11+ support
    dependencies: [
        .package(url: "https://github.com/ipedro/Inspector.git", .upToNextMajor(from: "2.0.0"))
    ]
    
    // For projects with iOS 14+ support
    dependencies: [
        .package(url: "https://github.com/ipedro/Inspector.git", .upToNextMajor(from: "3.0.0"))
    ]

    Setup

    After a successful installation, all you need to do is start the Inspector after your app finishes launching in SceneDelegate.swift or AppDelegate.swift. You can optionally add your own custom content, and tweak some configurations.

    SceneDelegate.swift

    // Scene Delegate Example
    
    import UIKit
    
    // Your application will not be rejected if you include the Inspector framework in your final bundle, however it's recommended that you import it only when debugging.
    
    #if DEBUG
    import Inspector
    #endif
    
    final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
        var window: UIWindow?
    
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            guard let _ = (scene as? UIWindowScene) else { return }
    
            (...)
            
            #if DEBUG
            Inspector.setConfiguration(...) // Optional. Add link to InspectorConfiguration
            Inspector.setCustomization(...) // Optional. Pass an object that conforms to the `InspectorCustomizationProviding` protocol.
            Inspector.start()
            #endif
        }
    
        (...)
    }

    AppDelegate.swift

    // App Delegate Example
    
    import UIKit
    
    // Your application will not be rejected if you include the Inspector framework in your final bundle, however it's recommended that you import it only when debugging.
    
    #if DEBUG
    import Inspector
    #endif
    
    final class AppDelegate: UIResponder, UIApplicationDelegate {
        var window: UIWindow?
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {        
            (...)
    
            #if DEBUG
            Inspector.setConfiguration(...) // Optional. Add link to InspectorConfiguration
            Inspector.setCustomization(...) // Optional. Pass an object that conforms to the `InspectorCustomizationProviding` protocol.
            Inspector.start()
            #endif
    
            return true
        }
    
        (...)
    }

    SwiftUI (Beta)

    Please note that SwiftUI support is in early stages and any feedback is welcome.

    // Add to your main view, or another view of your choosing
    
    import Inspector
    import SwiftUI
    
    struct ContentView: View {
        @State var text = "Hello, world!"
        @State var date = Date()
        @State var isInspecting = false
    
        var body: some View {
            NavigationView {
                ScrollView {
                    VStack(spacing: 15) {
                        DatePicker("Date", selection: $date)
                            .datePickerStyle(GraphicalDatePickerStyle())
    
                        TextField("text field", text: $text)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            .padding()
    
                        Button("Inspect") {
                            isInspecting.toggle()
                        }
                        .padding()
                    }
                    .padding(20)
                }
                .inspect(
                    isPresented: $isInspecting,
                    viewHierarchyLayers: nil,
                    elementColorProvider: nil,
                    commandGroups: nil,
                    elementLibraries: nil
                )
                .navigationTitle("SwiftUI Inspector")
            }
        }
    }

    Enable Key Commands (Recommended)

    Extend the root view controller class to enable Inspector key commands.

    // Add to your root view controller.
    
    #if DEBUG
    override var keyCommands: [UIKeyCommand]? {
        return Inspector.keyCommands
    }
    #endif

    Remove framework files from release builds (Recommended)

    In your app target:

    • Add a New Run Script Phase as the last phase.
    • Then paste the script below to remove all Inspector related files from your release builds.
    # Run Script Phase that removes `Inspector` and all its dependecies from release builds.
    
    if [ $CONFIGURATION == "Release" ]; then
        echo "Removing Inspector and dependencies from $TARGET_BUILD_DIR/$FULL_PRODUCT_NAME/"
    
        find $TARGET_BUILD_DIR/$FULL_PRODUCT_NAME -name "Inspector*" | grep . | xargs rm -rf
        find $TARGET_BUILD_DIR/$FULL_PRODUCT_NAME -name "UIKeyCommandTableView*" | grep . | xargs rm -rf
        find $TARGET_BUILD_DIR/$FULL_PRODUCT_NAME -name "UIKeyboardAnimatable*" | grep . | xargs rm -rf
        find $TARGET_BUILD_DIR/$FULL_PRODUCT_NAME -name "UIKitOptions*" | grep . | xargs rm -rf
        find $TARGET_BUILD_DIR/$FULL_PRODUCT_NAME -name "Coordinator*" | grep . | xargs rm -rf
    fi
    

    Presenting the Inspector

    The inspector can be presented from any view controller or window instance by calling the presentInspector(animated:_:) method. And that you can achieve in all sorts of creative ways, heres some suggestions.

    Using built-in Key Commands (Available on Simulator and iPads)

    After enabling Key Commands support, using the Simulator.app or a real iPad, you can:

    • Invoke Inspector by pressing Ctrl + Shift + 0.

    • Toggle between showing/hiding view layers by pressing Ctrl + Shift + 1-8.

    • Showing/hide all layers by pressing Ctrl + Shift + 9.

    • Trigger custom commands with any key command you want.

    With motion gestures

    You can also present Inspector using a gesture, like shaking the device. That way no UI needs to be introduced. One convienient way to do it is subclassing (or extending) UIWindow with the following code:

    // Declare inside a subclass or UIWindow extension.
    
    #if DEBUG
    open override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        super.motionBegan(motion, with: event)
    
        guard motion == .motionShake else { return }
    
        Inspector.present()
    }
    #endif

    Adding custom UI

    After creating a custom interface on your app, such as a floating button, or any other control of your choosing, you can call Inspector.present(animated:) yourself.

    // Add to any view controller if your view inherits from `UIControl`
    
    var myControl: MyControl
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        myControl.addTarget(self, action: #selector(tap), for: .touchUpInside)
    }
    
    @objc 
    private func tap(_ sender: Any) {
        Inspector.present(animated: true)
    }

    Customization

    Inspector allows you to customize and introduce new behavior on views specific to your codebase, through the InspectorCustomizationProviding Protocol.

    InspectorCustomizationProviding Protocol


    var viewHierarchyLayers: [Inspector.ViewHierarchyLayer]? { get }

    ViewHierarchyLayer are toggleable and shown in the Highlight views section on the Inspector interface, and also can be triggered with Ctrl + Shift + 1 - 8. You can use one of the default ones or create your own.

    Default View Hierarchy Layers:

    • activityIndicators: Shows activity indicator views.
    • buttons: Shows buttons.
    • collectionViews: Shows collection views.
    • containerViews: Shows all container views.
    • controls: Shows all controls.
    • images: Shows all image views.
    • maps: Shows all map views.
    • pickers: Shows all picker views.
    • progressIndicators: Shows all progress indicator views.
    • scrollViews: Shows all scroll views.
    • segmentedControls: Shows all segmented controls.
    • spacerViews: Shows all spacer views.
    • stackViews: Shows all stack views.
    • tableViewCells: Shows all table view cells.
    • collectionViewReusableVies: Shows all collection resusable views.
    • collectionViewCells: Shows all collection view cells.
    • staticTexts: Shows all static texts.
    • switches: Shows all switches.
    • tables: Shows all table views.
    • textFields: Shows all text fields.
    • textViews: Shows all text views.
    • textInputs: Shows all text inputs.
    • webViews: Shows all web views.
    • allViews: Highlights all views.
    • systemContainers: Highlights all system containers.
    • withIdentifier: Highlights views with an accessbility identifier.
    • withoutIdentifier: Highlights views without an accessbility identifier.
    • wireframes: Shows frames of all views.
    • internalViews: Highlights all.
    // Example
    
    var viewHierarchyLayers: [Inspector.ViewHierarchyLayer]? {
        [
            .controls,
            .buttons,
            .staticTexts + .images,
            .layer(
                name: "Without accessibility identifiers",
                filter: { element in
                    guard let accessibilityIdentifier = element.accessibilityIdentifier?.trimmingCharacters(in: .whitespacesAndNewlines) else {
                        return true
                    }
                    return accessibilityIdentifier.isEmpty
                }
            )
        ]
    }

    var elementIconProvider: Inspector.ElementIconProvider? { get }

    Return your own icons for custom classes or override exsiting ones. Preferred size is 32 x 32
    
    // Example
    
    var elementIconProvider: Inspector.ElementIconProvider? {
        .init { view in
            switch view {
            case is MyView:
                return UIImage(named: "my-view-icon-32")
                
            default:
                // you can alwayws fallback to default icons
                return nil
            }
        }
    }

    var elementColorProvider: Inspector.ElementColorProvider? { get }

    Return your own color scheme for the hierarchy label colors, instead of (or to extend) the default color scheme.

    // Example
    
    var elementColorProvider: Inspector.ElementColorProvider? {
        .init { view in
            switch view {
            case is MyView:
                return .systemPink
                
            default:
                // you can alwayws fallback to default color scheme if needed
                return nil
            }
        }
    }

    var commandGroups: [Inspector.CommandGroup]? { get }

    Command groups appear as sections on the main Inspector UI and can have key command shortcuts associated with them, you can have as many groups, with as many commands as you want.

    // Example
    
    var commandGroups: [Inspector.CommandGroup]? {
        guard let window = window else { return [] }
        
        [
            .group(
                commands: [
                    .command(
                        title: "Reset",
                        icon: .exampleCommandIcon,
                        keyCommand: .control(.shift(.key("r"))),
                        closure: {
                            // Instantiates a new initial view controller on a Storyboard application.
                            let storyboard = UIStoryboard(name: "Main", bundle: nil)
                            let vc = storyboard.instantiateInitialViewController()
    
                            // set new instance as the root view controller
                            window.rootViewController = vc
                            
                            // restart inspector
                            Inspector.restart()
                        }
                    )
                ]
            )
        ]
    }

    var elementLibraries: [Inspector.ElementPanelType: [InspectorElementLibraryProtocol]] { get }

    Element Libraries are entities that conform to InspectorElementLibraryProtocol and are each tied to a unique type. Pro-tip: Use enumerations.

    // Example
    
    var elementLibraries: [Inspector.ElementPanelType: [InspectorElementLibraryProtocol]] {
        [.attributes: ExampleElementLibrary.allCases]
    }
    // Element Library Example
    
    import UIKit
    import Inspector
    
    enum ExampleAttributesLibrary: InspectorElementLibraryProtocol, CaseIterable {
        case roundedButton
    
        var targetClass: AnyClass {
            switch self {
            case .roundedButton:
                return RoundedButton.self
            }
        }
    
        func sections(for object: NSObject) -> InspectorElementSections {
            switch self {
            case .roundedButton:
                return .init(with: RoundedButtonAttributesSectionDataSource(with: object))
            }
        }
    }
    // Element Section Data Source
    
    #if DEBUG
    import UIKit
    import Inspector
    
    final class RoundedButtonAttributesSectionDataSource: InspectorElementSectionDataSource {
        var state: InspectorElementSectionState = .collapsed
    
        var title: String = "Rounded Button"
    
        let roundedButton: RoundedButton
    
        init?(with object: NSObject) {
            guard let roundedButton = object as? RoundedButton else {
                return nil
            }
            self.roundedButton = roundedButton
        }
    
        enum Properties: String, CaseIterable {
            case animateOnTouch = "Animate On Touch"
            case cornerRadius = "Round Corners"
            case backgroundColor = "Background Color"
        }
    
        var properties: [InspectorElementProperty] {
            Properties.allCases.map { property in
                switch property {
                case .animateOnTouch:
                    return .switch(
                        title: property.rawValue,
                        isOn: { self.roundedButton.animateOnTouch }
                    ) { animateOnTouch in
                        self.roundedButton.animateOnTouch = animateOnTouch
                    }
    
                case .cornerRadius:
                    return .switch(
                        title: property.rawValue,
                        isOn: { self.roundedButton.roundCorners }
                    ) { roundCorners in
                        self.roundedButton.roundCorners = roundCorners
                    }
    
                case .backgroundColor:
                    return .colorPicker(
                        title: property.rawValue,
                        color: { self.roundedButton.backgroundColor }
                    ) { newBackgroundColor in
                        self.roundedButton.backgroundColor = newBackgroundColor
                    }
                }
            }
        }
    }
    
    #endif

    Donate

    You can support development with PayPal.


    Credits

    Inspector is owned and maintained by Pedro Almeida. You can follow him on Twitter at @ipedro for project updates and releases.


    License

    Inspector is released under the MIT license. See LICENSE for details.

    Visit original content creator repository https://github.com/ipedro/Inspector
  • firmware-analysis-plus

    Firmware Analysis Plus (Fap)

    Python 3.7+ Ubuntu 20.04 issues issues license

    👉 English

    上游项目支持:binwalkfirmadynefirmware-analysis-toolkit

    firmware-analysis-plusFap)主要用于常见路由器固件的仿真,可以进行固件的安全测试。感谢以下开源项目:binwalk 提供优秀的固件提取 API,firmadyne 提供优秀的固件仿真核心支持,firmware-analysis-toolkit 提供简化流程的思想。

    Fap 只是站在巨人的肩膀上,做出改进和定制,提供一个更加高效的仿真平台。包括精简不必要组件,优化仿真流程,优化网络环境大幅压缩安装时间,修复若干 bug,一键仿真固件。其原理主要包括两点

    • qemu 提供多种架构指令的模拟,使用预先编译好的内核启动固件中的核心业务;
    • 多数嵌入式设备含有一个 nvram 芯片,保存一些重要的配置信息,firmadyne 实现一个新的 libnvram.so 库文件,通过代码模拟固件启动时加载 nvram 配置信息的行为。

    推荐环境:Ubuntu 20.04 + binwalk-f4a5759,如果配置环境出错,可以直接下载打包好的 VMware 虚拟机镜像;也可以使用 docker-menu.sh 脚本建立 Docker 容器,Docker 国内需要使用科学上网或配置源。

    Fap 常见用法

    安装

    git clone https://github.com/liyansong2018/firmware-analysis-plus.git
    cd firmware-analysis-plus
    ./setup.sh

    配置

    修改 fap.config 文件中的密码,改为 root 系统用户的密码

    运行

    ┌──(lys㉿kali)-[~/Documents/IoT/firmware-analysis-plus]
    └─$ ./fap.py -q ./qemu-builds/2.5.0/ ./testcases/wnap320_V3.7.11.4_firmware.tar               
    
                 
                    ______   _                ___                 
                    |  ___| (_)              / _ \                
                    | |_     _   _ __ ___   / /_\ \  _ __    ___  
                    |  _|   | | | '_ ` _ \  |  _  | | '_ \  / __| ++
                    | |     | | | | | | | | | | | | | | | | \__ \ 
                    \_|     |_| |_| |_| |_| \_| |_/ |_| |_| |___/
    
                    Welcome to the Firmware Analysis Plus - v2.3.1
     By lys - https://github.com/liyansong2018/firmware-analysis-plus | @liyansong
        
    [+] Firmware: wnap320_V3.7.11.4_firmware.tar
    [+] Extracting the firmware...
    [+] Image ID: 3
    [+] Identifying architecture...
    [+] Architecture: mipseb
    [+] Building QEMU disk image...
    [+] Setting up the network connection, please standby...
    [+] Network interfaces: [('brtrunk', '192.168.0.100')]
    [+] Using qemu-system-mips from /home/lys/Documents/IoT/firmware-analysis-plus/qemu-builds/2.5.0
    [+] All set! Press ENTER to run the firmware...
    [+] When running, press Ctrl + A X to terminate qemu
    
    

    此时回车,可以进入路由器的 shell,也可以打开 Web 端路由器管理页面。

    关闭终端

    ./shutdown.py

    重置和删除中间文件

    ./reset.py

    参数 -t 用于更改固件网络地址推断的默认时间;参数 -q 用于配置 binwalk。

    FAQ

    解压镜像失败怎么办?

    最近的 binwalk 似乎存在问题,无法解压很多镜像(以前可以解压的镜像,例如 DIR-300A1_FW105b09.binHG532eV100R001C01B020_upgrade_packet.bin),因此推荐使用笔者打过 patch 的 binwalk,按照里面的说明直接编译即可。

    如果已经编译好了 binwalk,可以使用如下命令进行固件仿真

    ./fap.py -q ./qemu-builds/2.5.0/ ./testcases/wnap320_V3.7.11.4_firmware.tar 

    如何对固件进行重打包?

    fap 也支持不使用 binwalk 接口的模式,但是需要我们预先解压固件中的文件系统,并重新打包

    tar -czvf test.tar.gz *		# 一定要在固件文件系统的根目录下重新打包
    ./fap.py -q ./qemu-builds/2.5.0/ -b 0  ./testcases/test.tar.gz

    如果你想修改固件的内容,可参考 Wiki: 固件远程登录及调试

    支持的固件

    Fap 通用版(上游 firmadyne 项目提供)

    • wnap320_V3.7.11.4_firmware.tar
    • DIR-601_REVB_FIRMWARE_2.01.BIN
    • DIR890A1_FW103b07.bin
    • DIR-505L_FIRMWARE_1.01.ZIP
    • DIR-615_REVE_FIRMWARE_5.11.ZIP
    • DGL-5500_REVA_FIRMWARE_1.12B05.ZIP
    • WRT54G3G_2.11.05_ETSI_code.bin
    • NBG-416N_V1.00(USA.7)C0.zip
    • TEW-638v2%201.1.5.zip
    • Firmware_TEW-411BRPplus_2.07_EU.zip
    • DGND3700 Firmware Version 1.0.0.17(NA).zip
    • DIR-300A1_FW105b09.bin
    • HG532eV100R001C01B020_upgrade_packet.bin
    • DIR-860/865/880…

    Fap 定制版(针对特定固件定制的版本)

    相关研究

    本工具的相关介绍以及一些安全研究员利用此工具发现或者复现的安全漏洞。

    已发现的安全漏洞

    比较幸运的是,我们也是用该工具发现了一些路由器的安全漏洞,因此,使用 Fap 不仅可以复现 IoT 固件安全漏洞,提供靶场和演练环境,也可以用于漏洞挖掘。2021 年通过Fap 发现的可以实现远程代码执行的漏洞如下

    由于个人精力有限,加之上游项目 Firmadyne 架构近几年没有进行调整,因此本项目近期不会更新,但是此工具仍然可用于 IoT 漏洞挖掘或者安全研究。除基于 Firmadyne 的固件模拟项目之外,EMUX(ARMX) 也是仿真路由器固件不错的选择。

    其他推荐

    • EMBA – The firmware security analyzer(固件分析工具,集成 firmadyne,但是环境复杂)
    • EMUX – Firmware Emulation Framework (formerly ARMX)(路由器固件仿真)
    • FACT_core – Firmware Analysis and Comparison Tool
    Visit original content creator repository https://github.com/liyansong2018/firmware-analysis-plus
  • bwh-monitor-widget-for-scriptable

    English

    中文

    使用 Scriptable 基于 BandWagonHost(aff) API实现的服务器监控小组件。

    因此首先你需要去AppStore安装 Scriptable

    效果预览

    使用说明

    脚本说明

    项目包含 bwh_monitor.jsbwh_monitor_mini.js,建议对应使用中型小组件、小型小组件

    小型组件因空间问题,省略了字段描述,只保留了ICON。所有ICON对应关系如下:

    📌 Node info
    🖥 IP address
    🪫 RAM usage
    💿 Disk space
    ⏳ Data used
    ⏱️ Data reset time
    

    获取APIKEY

    进入Kiwi控制面板里的API模块,获取 veid、apikey

    添加组件、配置参数

    添加组件时,利用 Parameter 进行传参

    共有三个参数

    • veid:kiwi中获取的veid
    • apikey:kiwi中获取的apikey
    • title:[可选项]小组件的标题,如果不指定,则默认使用hostname作为标题

    传参方式如下:

    # 必传
    veid=1xxxxx&apikey=private_xxxxxxxxxxxxxxxxxx
    
    OR
    
    # title参数可选项
    veid=1xxxxx&apikey=private_xxxxxxxxxxxxxxxxxx&title=I_AM_Title
    
    

    感谢 & 参考

    灵感来源与代码copy,感谢 @412999826 开源

    https://community.nssurge.com/d/3131-vps

    https://github.com/412999826/surge-panel/blob/main/VPS-info.js

    ☕ 来杯咖啡

    如果你喜欢这个小组件,欢迎使用我的aff链接购买BandWagonHost服务器,谢谢

    BandWagonHost

    BandWagonHost备用

    English

    Using Scriptable to create a vps monitoring widget based on the BandWagonHost(aff) API.

    Therefore, you first need to install Scriptable from the App Store.

    Preview

    User Guide

    Description

    The project includes bwh_monitor.js and bwh_monitor_mini.js, and it is recommended to use medium widgets and small widgets accordingly.

    The small widget omits field descriptions due to space constraints and retains only the icons. The correspondence for all icons is as follows:

    📌 Node info
    🖥 IP address
    🪫 RAM usage
    💿 Disk space
    ⏳ Data used
    ⏱️ Data reset time
    

    Get API Key

    Access the API module in the Kiwi control panel to obtain veid and apikey.

    Add component and configure parameters.

    When adding a component, use Parameter to pass arguments.

    There are three parameters:

    • veid: The veid obtained from Kiwi.
    • apikey: The apikey obtained from Kiwi.
    • title: [Optional] The title of the widget. If not specified, the hostname will be used as the default title.

    The parameters can be passed as follows:

    # Required parameters
    veid=1xxxxx&apikey=private_xxxxxxxxxxxxxxxxxx
    
    OR
    
    # The title parameter is optional
    veid=1xxxxx&apikey=private_xxxxxxxxxxxxxxxxxx&title=I_AM_Title
    
    

    Thank you & References

    Inspiration and code copied from, thanks to @412999826 for open-sourcing.

    https://community.nssurge.com/d/3131-vps

    https://github.com/412999826/surge-panel/blob/main/VPS-info.js

    ☕ Buy Me A Coffee

    If you like this widget, feel free to use my affiliate link to purchase BandWagonHost servers. Thank you!

    BandWagonHost

    BandWagonHost Mirror

    Visit original content creator repository https://github.com/f1tz/bwh-monitor-widget-for-scriptable