Compare commits

...

40 Commits

Author SHA1 Message Date
Christoph J. Scherr f79b8b5d4d add tee thing 2024-08-01 12:58:16 +02:00
Christoph J. Scherr 4241cf5260
gauss small 2024-03-14 16:13:58 +01:00
Christoph J. Scherr 564b0cd011
replace semicolons with greek questionmarks 2024-03-06 13:51:02 +01:00
Christoph J. Scherr 95866bca81 stdin check with usage 2023-09-18 13:15:46 +02:00
Christoph J. Scherr a80c723a32 fix hd seek 2023-09-15 13:10:15 +02:00
Christoph J. Scherr 3465c56c2e hd from stdin 2023-09-14 17:56:26 +02:00
Christoph J. Scherr f12c1141eb todo 2023-09-14 17:46:03 +02:00
Christoph J. Scherr 2e39e89f37 keyboard handle 2023-09-14 17:45:13 +02:00
Christoph J. Scherr 502851d027 set name 2023-09-14 17:42:35 +02:00
Christoph J. Scherr bc159a2d24 force dump 2023-09-14 17:35:20 +02:00
Christoph J. Scherr bf9a01d7ba hexdumper non blocking io 2023-09-14 17:10:34 +02:00
Christoph J. Scherr 61dbf7a500 basic hexdumper 2023-09-14 16:33:11 +02:00
Christoph J. Scherr 778abfa7cc difficulty hexdump 2023-09-08 00:04:23 +02:00
Christoph J. Scherr 8e31d1063f caesar bonus and hints 2023-09-08 00:02:42 +02:00
Christoph J. Scherr 883e9c94ec add caesar script
tasks update
2023-09-07 23:41:45 +02:00
Christoph J. Scherr e296d8f97d caesar 2023-09-07 23:35:58 +02:00
Christoph J. Scherr afade771fa hexdumper task 2023-09-07 18:26:55 +02:00
Christoph J. Scherr 06194f0903 regex task solution 2023-09-05 16:25:06 +02:00
Christoph J. Scherr 7d1c18101a regex stuff 2023-09-05 16:15:17 +02:00
Christoph J. Scherr 2e23190dfe formatting 2023-09-05 15:37:01 +02:00
Christoph J. Scherr 07f2a5d728 add link to metasyntactic 2023-09-05 15:34:40 +02:00
Christoph J. Scherr 0a7021255c add regex task 2023-09-05 15:30:58 +02:00
Christoph J. Scherr d7dbefc851 password gen task 2023-09-05 11:19:44 +02:00
Christoph J. Scherr 90535e3237 basic password generator 2023-09-05 10:59:21 +02:00
Christoph J. Scherr 25ddac10df subtask numbering 2023-09-05 10:28:41 +02:00
Christoph J. Scherr 7f7cd3677d make task more clear 2023-09-05 10:26:50 +02:00
Christoph J. Scherr 0a8f6e5b53 add curl notice 2023-09-05 09:19:09 +02:00
Christoph J. Scherr 5ce6e095bc add author notice 2023-09-04 23:21:54 +02:00
Christoph J. Scherr 55ddaafdc7 perfection of first tasks 2023-09-04 23:18:57 +02:00
Christoph J. Scherr f0ec2e26ce working webserver 2023-09-04 22:19:23 +02:00
Christoph J. Scherr 3106a55d8e fibbonaci 2023-09-04 20:43:25 +02:00
Christoph J. Scherr 2297220759 miniweb 2023-09-04 19:09:18 +02:00
Christoph J. Scherr fa615d8321 fix spoiler tags 2023-09-04 17:55:54 +02:00
Christoph J. Scherr ecfc98be04 add basic webserver task 2023-09-04 17:53:28 +02:00
Christoph J. Scherr 426c456e1c add basic tasks for learners 2023-09-04 17:51:48 +02:00
Christoph J. Scherr 2d4141937a md5 stuff 2023-09-04 16:57:28 +02:00
Christoph J. Scherr d3483e229e
mini change 2023-04-21 00:48:47 +02:00
Christoph J. Scherr 207673382f idk what changed 2023-04-21 00:44:30 +02:00
Christoph J. Scherr 2c7f6fc759 Merge branch 'curses-stopwatch' 2023-04-21 00:38:44 +02:00
Christoph J. Scherr 7c437fb759 Merge pull request 'curses-stopwatch' (#8) from curses-stopwatch into master
Reviewed-on: #8
2023-04-21 00:35:21 +02:00
18 changed files with 1055 additions and 9 deletions

View File

@ -1,4 +0,0 @@
# Things i would like to add to this repository
Caesar-encryption, decryption, brute force
calculate determinante (german, idk the english word) of a matrix

27
TODO.norg Normal file
View File

@ -0,0 +1,27 @@
This is a list of tasks that would be cool to add.
* Tasks
** Basic
*** Files
- (-) Hex dumper
- (x) Dump basic files with format
- (x) Dump basic files with chars
- (x) Be able to dump larger files or put out an error
- (x) Stop reading when read gets blocked /somehow/
Simple syscall
- (x) Wait for new input when the file is lazy
- (x) Install script to system
Using update-alternatives is the most handy
- (x) Accept input from stdin when no file is given
- (x) Print error when no file and stdin is given
- ( ) Process only first N or last N Bytes
- ( ) Write a complete task for this stuff
*** Networking
- ( ) Mini curl
*** Packaging
- ( ) Installing a package to your system
- ( ) Building a library
** Cryptography
*** Signature
- ( ) Check a signature with OpenSSL

489
Tasks.md Normal file
View File

@ -0,0 +1,489 @@
# Tasks for beginners
This document contains some tasks for Python beginners. It does not aim to teach general
programming techniques, only how to use Python. I try to avoid unrealistic tasks.
In case you have somehow gotten this document from another source,
[this](https://git.cscherr.de/PlexSheep/py-basic/src/branch/master/Tasks.md) is the original
source, where the links should hopefully work. If something does not work feel free to contact
me at [software@cscherr.de](mailto:admin@cscherr.de).
## MD5 Hashchecker
### A. Produce a single MD5 Hash
Difficulty: 1/5
1. Hash the string `foobar19` with the MD5 hashing algorithm.
<details>
<summary>Hints</summary>
- Use Pythons `hashlib`.
- Your hashing function does not take strings for input, only raw data (bytes).
- You need to explicitly tell your hash to actually process the input.
- When printing your results, the result may be interpreted as data for characters.
You want the numeric value of the result in Hexadecimal.
</details>
<details>
<summary>Solution</summary>
The MD5 hash of `foobar19` is `fa5c65d5438f849387d3fdda2be4dd65`.
[Example Code](src/md5.py)
</details>
### B. Hash multiple values and search for specific ones.
Difficulty: 2/5
1. Find a way to produce strings with the basis `foobar` with appended numbers from `000000` to
`999999`.
```text
1. `foobar000000`
2. `foobar000001`
3. `foobar000002`
...
999998. `foobar999998`
999999. `foobar999999`
```
2. Hash all these with the MD5 hashing algorithm.
3. Find the exact numbers, how many of these hashes start with `00`
4. **Bonus**:
1. If MD5 was a good / perfect Hashing algorithm (it is definitely not),
how many matches for a `00` prefix should exist? Why?
2. How many matches for $0$ to $50000$? How many matches for $0$ to $50.000.000$?
<details>
<summary>Testvectors</summary>
Last 5 Matches
```text
999384 | 009671fd23fa783df1fff63516e5d115
999751 | 00ec2ade58f75c44b7300294497f7fb1
999844 | 009cfd7949b577a3311d9db3ee49c15d
999852 | 006fe04f7d3f710f93d3e6324506154a
999902 | 00c063364ddffa1bdf338dfcf0319424
```
</details>
<details>
<summary>Hints</summary>
- Use a for loop to do the thing X times
- Use Pythons string formatting to put the numbers and string together
- Use Options for the `%d` Placeholder to get $0$ to be displayed as `000000`
- After hashing, check if your current hash matches the search.
Print it if that is the case to see if the match is a false positive.
- Increment a number on each match. The value of that number after the loop is how many
Hashes start with `00` for this task.
</details>
<details>
<summary>Solution</summary>
There are 3889 hashes for `foobar000000` to `foobar999999` that produce an MD5 Hash that starts
with `00`.
[Code Example](src/md5range.py)
**Bonus**
We want $N/16^2$ occurrences for an ideal hashing algorithm, where $N$ is the maximum of our range
$+ 1$.
$16^2$ comes from $2$ characters in a range of `0` to `e` (Hexadecimal).
We want the hashing algorithm to spread out as much as possible, no value should be more common
than any other value. This is essential for the security of the hashing algorithm.
| Value | Ideal Occurences |
|--------------|------------------|
| $1.000.000$ | $\approx 3906$ |
| $500.000$ | $\approx 1953$ |
| $50.000.000$ | $\approx 195312$ |
</details>
### C. Find earliest hash that fits criteria
Difficulty: 2/5
1. Find the earliest integer $X$ for `foobarXXXXXX` (where $X$ is an iterator as in the last
subtask) that produces an MD5 hash that starts with `2718`.
<details>
<summary>Hints</summary>
- You can reuse most code from the last subtask.
- Match against the new prefix, but stop when you find it.
- Display the index number in each loop iteration.
</details>
<details>
<summary>Solution</summary>
The first hash with prefix `2718` occurs at $i=70559$.
```text
070559 | 2718e5ee6d05091ce6dad023e55ee19c
```
[Code Example](src/md5range-4.py)
</details>
## Super basic web server
Difficulty: 3/5
1. Program a Python web server that writes "Python is not so hard" in your Browser (or in `cURL`).
Use `http.server`.
<details>
<summary>Hints</summary>
- Use `http.server.SimpleHTTPRequestHandler` and `io.BytesIO`.
- Define your own class that inherits `SimpleHTTPRequestHandler`.
- You don't need to implement `do_GET()`.
- Implement your own `send_head()` method. This is the method that writes your response (not
completely on it's own, but unless you feel like inspecting standard libraries, just do what
I'm saying.).
- `send_head()` should take no arguments (other than `self`) and return some readable buffer.
- Don't forget to set the headers for HTTP before sending the body.
- Your OS might block hosting to ports < 1000. Try to host your web server to `localhost:8080`.
</details>
<details>
<summary>Solution</summary>
Take a look at the provided Code Example.
[Code Example](src/miniweb.py)
</details>
## Random Password generator
Difficulty: 2/5
1. Generate a string of 16 random alphanumeric characters.
2. When starting your script, take a number for a CLI Argument. Generate a random string of this
length.
3. **Bonus**
- How many possible strings consisting of 16 alphanumeric characters can exist?
- Add the possibility for a second argument `-v` that indicates your script should be more
verbose.
- print the security bits ($log_2(L)$ where $L$ is the total number of possibilities) when the
`-v` flag is applied
Example:
```bash
$ python ./randomString.py 60
n51uxDLu3BnxZ1D00gYKYRcG2jh1Y6uulHgrJ0TK3w5FtWl6wm8U0azNtxw0
# ^^^^ the above is 60 characters ^^^^
```
<details>
<summary>Hints</summary>
- Use `random.choice` to generate a random character
- build your own alphabet string
- Use `sys.argv` to access the CLI Arguments
</details>
<details>
<summary>Solution</summary>
Take a look at the provided Code Example.
[Code Example](src/randomString.py)
**Bonus**
There are 62 alphanumeric characters (A-Z), (a-z), (0-9).
With $N$ characters, there are $62^N$ possible variants.
For $N=16$ that's $62^{16} = 47.672.401.706.823.533.450.263.330.816$ possible variants.
Security people measure security in Bits ($2^x$). You can calculate the bits of security with the
logarithm base 2.
$S = log_2(62^N)$.
We can immediately see that longer passwords are *exponentially* more secure than
more complex passwords (passwords that make use of complicated characters). For each bit, the
security of the password is doubled.
For our example of $N=16$ we can calculate the security of the password like this:
$S=log_2(62^{16}) \approx 95.27$
That number of security bits is pretty good for passwords. However it does not cost you anything to
just make your passwords longer than that, and give attackers no chance to break them by brute
force.
</details>
## String Parsing with Regular Expressions
Difficulty: 2/5
<details>
<summary>Text</summary>
The text is large, read it [here](data/metasyntactic.md) and find the raw text for your program
[here](https://git.cscherr.de/PlexSheep/py-basic/raw/branch/master/data/metasyntactic.md).
</details>
1. Use a regular expression (regex) to find all words that start with a lowercase character with a
following vowel character, in which no 'x', z' or 'y' follows the vowel in the given Text.
It is not allowed to store the text in source code, you must load it from an outside source,
such as a file.
Examples:
| Original | is Match? |
|----------|-----------|
| foo | yes |
| foobar | yes |
| tayfoo | no |
| baz | no |
| qux | no |
| Foo | no |
| bAR | yes |
| far | yes |
A hint that you don't want to miss:
Use [regex101.com](https://regex101.com) if you are not already a REGEX expert.
<details>
<summary>Hints</summary>
- use `open()` to open your file for reading.
- use the `read()` method to read the file out.
- Use the `re` library
- Use `\b` to match a word boundary
- Use ranges `[5-9]`
- You can set a higher precedence by putting things in braces `(ABC)`.
- You can connect two expressions with `A|B` to use either `A` or `B`
- Use global mode.
</details>
<details>
<summary>Solution</summary>
There should be $374$ matches.
A regex that matches the requirements is `\b[a-z][AEIOUaeiou]([a-w]|[A-W])`.
[Code Example](src/tasks/regex.py)
</details>
## Primitive Cryptography
This section covers some ancient and / or primitive methods of Cryptography.
These are relatively easy to code and give a basic understanding of used
concepts.
### A. The Caesar Cipher
Difficulty: 2/5
<details>
<summary>Text</summary>
```text
Gxhobf bl t kxytvmhk, tgw lhfxmbfxl kxwtvmhk, bg max mktwbmbhg hy Obf (pabva bmlxey wxkboxl ykhf
Lmxobx). Bm bl ghm t kxpkbmx unm t vhgmbgntmbhg tgw xqmxglbhg hy Obf. Ftgr vehgxl tgw wxkbotmboxl
xqblm, lhfx oxkr vexoxk—unm ghgx tkx Obf. Gxhobf bl unbem yhk nlxkl pah ptgm max zhhw itkml hy
Obf, tgw fhkx.
````
</details>
1. The text above has been cyphered with the Caesar cipher, a timeless,
classical algorithm that abstracts the meaning of text away and arguably
an early form of encryption. Your task is to decipher it back into readable
text.
2. **Bonus**
- What if you didn't just try all possible combinations? How could you find
the key without trying until you find it?
**The cipher**
For the Caesar cipher, all letters are shifted by the value of the key.
**Examples**
`foo Bar` becomes `gpp Cbs` when shifted by $1$.
Try to find out the rest for yourself.
<details>
<summary>Hints</summary>
- You can use the `ascii` codes of the letters to your advantage.
- You need to distinguish between lower and upper case.
- To roll back from back from a too high index back into the range of real
letters. To do that you can use the modulo operation, which computes the
remainder of a division by x. This is actually finite field arithmetic,
but don't get so deep into the math.
- It is handy to have a command line argument for key and source text.
</details>
<details>
<summary>Solution</summary>
I ciphered the text with the key $19$. The original, deciphered text is:
<details>
<summary>Text</summary>
```text
Neovim is a refactor, and sometimes redactor, in the tradition of Vim (which itself derives from
Stevie). It is not a rewrite but a continuation and extension of Vim. Many clones and derivatives
exist, some very clever—but none are Vim. Neovim is built for users who want the good parts of
Vim, and more.
````
</details>
To decipher, you just apply the shifting of number backwards, or with the key
$-19$ (that's the same thing!).
[Code Example](src/caesar.py)
**Bonus**
One other way you could try to *recover* the key with is by statistical
analysis. Western languages (like English, German, etc.) have some letters,
words, combinations of letters, that are more common than others. These follow
a [statistical distribution](https://en.wikipedia.org/wiki/Letter_frequency).
The letter that is by far the most common in English is `e`.
With this information, you could count the occurrences for each letter and find
that the graph of frequencies looks the same -- only shifted by a couple
letters. That difference is your key.
Another way to try to recover the key is by looking at obvious words. The second
word in the cipher text is a single `t`. How many (common) words do you know
that only have one letter? I only know `a`. If we calculate the difference,
again, we get $19$, which is the key.
</details>
## Making a Hexeditor
In this section, we're building a little hexeditor. You will be able to install
it on your system and use it instead of the `hexdump` and `xxd` built into most
Linux distributions.
Hexdumping is actually really simple, all you have to do is read a file and
print it's direct content interpreted as numbers in hexadecimal. Apply some
fancy string formatting and we're done!
The editing part is a lot harder. It requires us to build a functioning TUI -
Terminal User Interface, as working with command line arguments or regular
reading from stdin won't help us much for editing a file. (if that's your thing,
use `ed`.).
Note: If you're looking for a great, fully featured hexeditor, I'd recommend
`bvi` ("binary vi"), which is packaged by most distributions.
-> `apt-get install bvi` <-
Note: I have no Idea how to install a python script as executable on windows, I
don't like windows either, so no support for installing stuff on windows.
### A. Hexdumper
Difficulty: 3/5
1. Dump the data of [data/metasyntactic.md](./data/metasyntactic.md) -- In
Hexadecimal.
2. Make the dumped Bytes look pretty, something like the example below:
3. Make use of command line arguments to add a help option (triggered with `-h` or
`--help`) and a `-C` or `--chars` option that adds another section that
prints the bytes interpreted as text. Those bytes that have no text
representation should be displayed as `.`. You may use the `argparse` library
to work with the arguments.
<details>
<summary>Hexdump Example Display</summary>
`data/metasyntactic.md` should look like this when hexdumped:
```text
Line Data
=================================================
0000000 | 6f4e 6574 203a 6854 7369 6920 2073 6874
0000010 | 2065 6957 696b 6570 6964 2061 6170 6567
0000020 | 6620 726f 6d20 7465 7361 6e79 6174 7463
0000030 | 6369 7620 7261 6169 6c62 7365 6920 206e
0000040 | 6e45 6c67 7369 2c68 3220 3230 2d33 3930
0000050 | 302d 2e35 4620 6e69 2064 6874 0a65 7075
0000060 | 7420 206f 6164 6574 6f20 6972 6967 616e
0000070 | 206c 685b 7265 5d65 6828 7474 7370 2f3a
0000080 | 652f 2e6e 6977 696b 6570 6964 2e61 726f
0000090 | 2f67 6977 696b 4d2f 7465 7361 6e79 6174
00000a0 | 7463 6369 765f 7261 6169 6c62 2965 0a2e
00000b0 | 230a 4d20 7465 7361 6e79 6174 7463 6369
00000c0 | 7620 7261 6169 6c62 0a65 230a 2023 6f54
00000d0 | 6c6f 0a73 460a 6f72 206d 6957 696b 6570
00000e0 | 6964 2c61 7420 6568 6620 6572 2065 6e65
00000f0 | 7963 6c63 706f 6465 6169 540a 6968 2073
0000100 | 7261 6974 6c63 2065 7369 6120 6f62 7475
0000110 | 6d20 7465 7361 6e79 6174 7463 6369 7620
...
```
And like this when hexdumped with `-C`:
```text
Line Data Text
======================================================================
0000000 | 6f4e 6574 203a 6854 7369 6920 2073 6874 |Note: This is th|
0000010 | 2065 6957 696b 6570 6964 2061 6170 6567 |e Wikipedia page|
0000020 | 6620 726f 6d20 7465 7361 6e79 6174 7463 | for metasyntact|
0000030 | 6369 7620 7261 6169 6c62 7365 6920 206e |ic variables in |
0000040 | 6e45 6c67 7369 2c68 3220 3230 2d33 3930 |English, 2023-09|
0000050 | 302d 2e35 4620 6e69 2064 6874 0a65 7075 |-05. Find the.up|
0000060 | 7420 206f 6164 6574 6f20 6972 6967 616e | to date origina|
0000070 | 206c 685b 7265 5d65 6828 7474 7370 2f3a |l [here](https:/|
0000080 | 652f 2e6e 6977 696b 6570 6964 2e61 726f |/en.wikipedia.or|
0000090 | 2f67 6977 696b 4d2f 7465 7361 6e79 6174 |g/wiki/Metasynta|
00000a0 | 7463 6369 765f 7261 6169 6c62 2965 0a2e |ctic_variable)..|
00000b0 | 230a 4d20 7465 7361 6e79 6174 7463 6369 |.# Metasyntactic|
00000c0 | 7620 7261 6169 6c62 0a65 230a 2023 6f54 | variable..## To|
00000d0 | 6c6f 0a73 460a 6f72 206d 6957 696b 6570 |ols..From Wikipe|
00000e0 | 6964 2c61 7420 6568 6620 6572 2065 6e65 |dia, the free en|
00000f0 | 7963 6c63 706f 6465 6169 540a 6968 2073 |cyclopedia.This |
...
```
</details>
<details>
<summary>Hints</summary>
</details>
<details>
<summary>Solution</summary>
[Code Example](./src/hexdumper.py)
</details>
### B. Packaging your hexdumper
1. Install `pip`, on debian based systems you can do that with `apt-get install
python3-pip`.

167
data/metasyntactic.md Normal file
View File

@ -0,0 +1,167 @@
Note: This is the Wikipedia page for metasyntactic variables in English, 2023-09-05. Find the
up to date original [here](https://en.wikipedia.org/wiki/Metasyntactic_variable).
# Metasyntactic variable
## Tools
From Wikipedia, the free encyclopedia
This article is about metasyntactic variables in computer science and programming. For metasyntactic
variables as used in formal logic, see Metavariable (logic). For usage in spoken languages, see
Placeholder name.
A metasyntactic variable is a specific word or set of words identified as a placeholder in computer
science and specifically computer programming. These words are commonly found in source code and are
intended to be modified or substituted before real-world usage. For example, foo and bar are used in
over 330 Internet Engineering Task Force Requests for Comments, the documents which define
foundational internet technologies like HTTP (web), TCP/IP, and email protocols.[1][2]
By mathematical analogy, a metasyntactic variable is a word that is a variable for other words,
just as in algebra letters are used as variables for numbers.[1]
Metasyntactic variables are used to name entities such as variables, functions, and commands whose
exact identity is unimportant and serve only to demonstrate a concept, which is useful for teaching
programming.
Common metasyntactic variables
Due to English being the foundation-language, or lingua franca, of most computer programming
languages, these variables are commonly seen even in programs and examples of programs written for other spoken-language audiences.
The typical names may depend however on the subculture that has developed around a given programming
language.
## General usage
Metasyntactic variables used commonly across all programming languages include foobar, foo, bar,
baz, qux, quux, corge, grault, garply, waldo, fred, plugh, xyzzy, and thud; several of these words
are references to the game Colossal Cave Adventure.[1][3]
A complete reference can be found in a MIT Press book titled The Hacker's Dictionary.
## Japanese
In Japanese, the words hoge (ほげ)[4] and fuga (ふが) are commonly used, with other common words
and variants being piyo (ぴよ), hogera (ほげら), and hogehoge (ほげほげ).[5][circular reference]
The origin of hoge as a metasyntactic variable is not known, but it is believed to date to the early
1980s.[5]
## French
In France, the word toto is widely used, with variants tata, titi, tutu as related placeholders.
One commonly-raised source for the use of toto is a reference to the stock character used to tell
jokes with Tête à Toto.[citation needed]
## Turkish
In Turkey, the words hede and hödö (usually spelt hodo due to ASCII-only naming constraints of
programming languages) are well-known metasyntactic variables stemmed from popular humorous cartoon
magazines of the 90's like LeMan. The words don't mean anything, and specifically used in place of
things that don't mean anything. The terms have been popularized to the masses by the actor and
stand-up comedian Cem Yılmaz in the late 90's and early 2000's.[6]
## Usage examples
A screenshot of a metasyntactic variable FOO assigned and echoed in an interactive shell session.
## C
See also: C programming language
In the following example the function name foo and the variable name bar are both metasyntactic
variables. Lines beginning with // are comments.
```c
// The function named foo
int foo(void)
{
// Declare the variable bar and set the value to 1
int bar = 1;
return bar;
}
```
## C++
See also: C++
Function prototypes with examples of different argument passing mechanisms:[7]
```cpp
void Foo(Fruit bar);
void Foo(Fruit* bar);
void Foo(const Fruit& bar);
Example showing the function overloading capabilities of the C++ language
void Foo(int bar);
void Foo(int bar, int baz);
void Foo(int bar, int baz, int qux);
```
## Python
Spam, ham, and eggs are the principal metasyntactic variables used in the Python programming
language.[8] This is a reference to the famous comedy sketch, "Spam", by Monty Python, the eponym
of the language.[9] In the following example spam, ham, and eggs are metasyntactic variables and
lines beginning with # are comments.
```python
# Define a function named spam
def spam():
# Define the variable ham
ham = "Hello World!"
# Define the variable eggs
eggs = 1
return
```
## IETF Requests for Comments
Both the IETF RFCs and computer programming languages are rendered in plain text, making it
necessary to distinguish metasyntactic variables by a naming convention, since it would not be
obvious from context.
Here is an example from the official IETF document explaining the e-mail protocols (from RFC 772 -
cited in RFC 3092):
```text
All is well; now the recipients can be specified.
S: MRCP TO:<Foo@Y> <CRLF>
R: 200 OK
S: MRCP TO:<Raboof@Y> <CRLF>
R: 553 No such user here
S: MRCP TO:<bar@Y> <CRLF>
R: 200 OK
S: MRCP TO:<@Y,@X,fubar@Z> <CRLF>
R: 200 OK
Note that the failure of "Raboof" has no effect on the storage of
mail for "Foo", "bar" or the mail to be forwarded to "fubar@Z"
through host "X".
```
(The documentation for texinfo emphasizes the distinction between metavariables and mere variables
used in a programming language being documented in some texinfo file as: "Use the @var command to
indicate metasyntactic variables. A metasyntactic variable is something that stands for another
piece of text. For example, you should use a metasyntactic variable in the documentation of a
function to describe the arguments that are passed to that function. Do not use @var for the names
of particular variables in programming languages. These are specific names from a program, so
@code is correct for them."[10])
Another point reflected in the above example is the convention that a metavariable is to be
uniformly substituted with the same instance in all its appearances in a given schema. This is in
contrast with nonterminal symbols in formal grammars where the nonterminals on the right of a
production can be substituted by different instances.[11]
Example data
SQL
It is common to use the name ACME in example SQL Databases and as placeholder company-name for the
purpose of teaching. The term 'ACME Database' is commonly used to mean a training or example-only
set of database data used solely for training or testing. ACME is also commonly used in
documentation which shows SQL usage examples, a common practice with in many educational texts as
well as technical documentation from companies such as Microsoft and Oracle.[12][13][14]

46
src/caesar.py Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
import sys
def internal(text: str, key: int) -> str:
cyphertext: str = ""
for c in text:
if ord(c) >= 65 and ord(c) <= 90: # uppercase letters
ci = ord(c) - ord('A')
add = ord('A')
#print(f"{c} is uppercase")
elif ord(c) >= 97 and ord(c) <= 122: # uppercase letters
ci = ord(c) - ord('a')
add = ord('a')
#print(f"{c} is lowercase")
else:
#print(f"not a letter: {c} ({ord(c)})")
# character is not a letter, just skip it
cyphertext += c
continue
ci += key
ci %= 26 # only 23 letters in the alphabet
#print(f"ci for {c}: {ci}")
cyphertext += chr(ci + add)
return cyphertext
if len(sys.argv) <= 2 or len(sys.argv) >= 5:
print("Takes two arguments: <SOURCE> <KEY> [-e]")
exit(1)
source: str = sys.argv[1]
target: str = ""
key = int(sys.argv[2])
if len(sys.argv) >= 4 and sys.argv[3] == "-e":
print("encrypting...")
target = internal(source, -key)
else:
print("decrypting...")
target = internal(source, key)
print("=" * 80)
print("%s" % target)

9
src/fib.py Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env python3
import sys
def fib(n):
fibs = [0, 1]
for i in range(2, n+1):
fibs.append(fibs[i-1] + fibs[i-2])
print(fibs)
return fibs[n]
fib(int(sys.argv[1]))

9
src/gauss.py Executable file
View File

@ -0,0 +1,9 @@
import sys
def small_gaussian_sum(n: int) -> int:
return int((n**2 + n) / 2)
if __name__ == "__main__":
if sys.argv.__len__() < 2:
print("provide a natural number as arg")
else:
print(small_gaussian_sum(int(sys.argv[1])))

34
src/greek_to_me.py Executable file
View File

@ -0,0 +1,34 @@
import os
import sys
def greek(path: str):
"""replace all semicolons in the given file with Greek question marks"""
contents: str = ""
with open(path, "r") as file:
contents = file.read()
contents = contents.replace(";", "\u037e")
with open(path, "w") as file:
file.write(contents)
file.flush()
def main():
"""
Turn all semicolons ';' of the target files into Greek question marks ';'.
For compilers and interpreters, this is a completely different character,
but to humans, it looks the same. The Rust compiler is smart enough to warn
us that it only looks like a semicolon. Use more Rust.
"""
if sys.argv.__len__() < 2:
print("provide filepaths as arguments")
paths: list[str] = []
for index, arg in enumerate(sys.argv):
if os.path.exists(arg) and os.path.isfile(arg) and index > 0:
paths.append(arg)
for path in paths:
greek(path)
if __name__ == "__main__":
main()

156
src/hexdumper.py Executable file
View File

@ -0,0 +1,156 @@
#!/usr/bin/env python3
import argparse
import os
import sys
import io
import fcntl # only for non blocking IO, if you dont know what it is, you can ignore it or study up
import select # to check if the file has data
# 2**30 bytes aka 1 Mebibyte
MAX_SIZE: int = 0x100000
def humanbytes(B):
"""Return the given bytes as a human friendly KB, MB, GB, or TB string."""
B = float(B)
KB = float(1024)
MB = float(KB ** 2) # 1,048,576
GB = float(KB ** 3) # 1,073,741,824
TB = float(KB ** 4) # 1,099,511,627,776
if B < KB:
return '{0} {1}'.format(B,'Bytes' if 0 == B > 1 else 'Byte')
elif KB <= B < MB:
return '{0:.2f} KB'.format(B / KB)
elif MB <= B < GB:
return '{0:.2f} MB'.format(B / MB)
elif GB <= B < TB:
return '{0:.2f} GB'.format(B / GB)
elif TB <= B:
return '{0:.2f} TB'.format(B / TB)
def main():
"""Dump a file"""
# arg parsing
parser = argparse.ArgumentParser(
prog="hd",
description="Dumps data as hex"
)
parser.add_argument("file", nargs='?', type=argparse.FileType('rb'), default=sys.stdin)
parser.add_argument("-c", "--chars", action="store_true")
parser.add_argument("-f", "--force", action="store_true") # ignore set limits
args = parser.parse_args()
# open file
try:
# Tl;Dr, use this unless you want to do some lower level stuff
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#file = open(args.file, "rb")
# the above is sufficient for most regular uses
#
# some "files" are "lazy" and block the reading process until they have
# content, like network connections, fifos, sockets, and so on.
# the following is a lower level approach to handling these. We
# basically call a part of the libc, telling it to open the file
# nonblocking. If something blocks, it will simply refuse.
#
# as far as i know, this only works on UNIX (like) systems. Windows
# is the only major exception.
# make a syscall that will open our file in readonly mode, nonblocking.
# if it did not exist and we write to it, it would be created with the
# perms: 644 (like `chmod 644 myfile`)
fd = args.file.fileno()
# now we make the fd into the high level python class `file`
file = os.fdopen(fd, "rb")
# i read somewhere that file.readline() does not work like this, but as
# we are reading binary data anyways, I don't care.
# check if the file is readable
if not select.select([file, ], [], [], 0.0)[0]:
print("no data from stdin, are you trying to dump a file?")
parser.print_usage()
sys.exit(1)
if not file.peek(1):
print("File is blocked, trying to wait...")
file = open(args.file, "rb")
except Exception as e:
print(f"Could not open file '{args.file}': {e}")
sys.exit(1)
# check if the file has a reasonable size to dump
try:
file.seek(0, os.SEEK_END)
flen = file.tell()
file.seek(0, os.SEEK_SET)
except io.UnsupportedOperation:
# some kinds of "files" like stdin are not seekable
flen = 0
if 0 != flen > MAX_SIZE:
print(f"""The file you are trying to dump is larger than 1M.\n\
Actual size: {humanbytes(flen)}\nrefusing to dump""")
if (0 != flen > MAX_SIZE) and not args.force:
print(f"The file you are trying to dump is larger than {humanbytes(MAX_SIZE)}.\n\n\
Actual size: {humanbytes(flen)}\n\nrefusing to dump. You can force dump the file with --force.")
sys.exit(2)
# print header
if args.chars:
print("Line Data Text")
print('=' * 68)
else:
print(f"Line Data")
print('=' * 48)
# every line should contain 16 bytes, so we need a loop that get's 16 bytes
# and then works with them
next: bytes = bytes(16)
index: int = 0
while len(next) == 16:
next = file.read(16)
if len(next) == 0:
# no data left to read
break
line: str = f"{index:07x} | "
# actual hexdumping
for i in range(16):
if i % 2 == 0:
if len(next) > i+1:
line += f"{next[i]:02x}{next[i+1]:02x} "
elif len(next) > i:
line += f"{next[i]:02x} "
else:
line += " "
else: continue
# if chars is enabled, print chars
if args.chars:
line += "| "
for b in next:
# special case for newline
if b == 0x0a:
line+= '' # official unicode symbol representing newlines
# only print regular characters
elif b > 0x20 and b < 0x7e:
line += chr(b)
elif b == 0x20:
line += '\u2420'
else:
line += '.'
print(line)
index += 16
file.close()
if __name__ == "__main__":
# when called directly (like executed from shell)
try:
main()
except KeyboardInterrupt:
# no need for an exception when the user presses ctrl c.
sys.exit(0)

6
src/md5.py Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import hashlib
import sys
to_hash = "foobar19"
hashed = hashlib.md5(to_hash.encode())
print(hashed.digest().hex())

19
src/md5range-4.py Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
import hashlib
BASE: str = "foobar"
MAX = 1000000
SEARCH = "2718"
count = 0
for i in range(0, MAX):
num: str = ("%06d" % i)
current = BASE + num
res = hashlib.md5(current.encode()).digest().hex()
if SEARCH == res[:4]:
count += 1
print("%06d | %s" % (i, res))
break
print(f"\nFound %d digests matching the search" % count)

18
src/md5range.py Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
import hashlib
BASE: str = "foobar"
MAX = 1000000
SEARCH = "00"
count = 0
for i in range(0, MAX):
num: str = ("%06d" % i)
current = BASE + num
res = hashlib.md5(current.encode()).digest().hex()
if SEARCH == res[:2]:
count += 1
print("%06d | %s" % (i, res))
print(f"\nFound %d digests matching the search" % count)

23
src/miniweb.py Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
import http.server
import io
TEXT = "Python is not so hard"
class MyHandler(http.server.SimpleHTTPRequestHandler):
def send_head(self) -> io.BytesIO:
body = TEXT.encode()
self.send_response(200)
self.send_header("Content-type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
return io.BytesIO(body)
address = ("127.0.0.1", 8080)
srv = http.server.HTTPServer(address, MyHandler)
srv.serve_forever()
# To query your web server go to http://localhost:8080
# OR from CLI and with headers:
# $ curl localhost:8080 -v

View File

@ -7,7 +7,7 @@ import time
def report_progress(filename, progress): def report_progress(filename, progress):
"""progress: 0-10""" """progress: 0-10"""
stdscr.addstr(0, 0, "Moving file: {0}".format(filename)) stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress)) stdscr.addstr(1, 0, "Total progress: [{1:20}] {0}%".format(progress * 5, "#" * progress))
stdscr.refresh() stdscr.refresh()
if __name__ == "__main__": if __name__ == "__main__":
@ -16,7 +16,7 @@ if __name__ == "__main__":
curses.cbreak() curses.cbreak()
try: try:
for i in range(10): for i in range(20):
report_progress("file_{0}.txt".format(i), i+1) report_progress("file_{0}.txt".format(i), i+1)
time.sleep(0.5) time.sleep(0.5)
finally: finally:

View File

@ -1,12 +1,20 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import random import random
import string import string
import math
import sys
alphabet = string.ascii_lowercase
alphabet += string.ascii_uppercase
alphabet += "0123456789"
def get_random_string(length): def get_random_string(length):
# choose from all lowercase letter # choose from all lowercase letter
letters = string.ascii_lowercase result_str = ''.join(random.choice(alphabet) for i in range(length))
result_str = ''.join(random.choice(letters) for i in range(length))
return result_str return result_str
print(get_random_string(20)) print(get_random_string(int(sys.argv[1])))
if len(sys.argv) >= 3 and sys.argv[2] == "-v":
security = math.log2(len(alphabet)**int(sys.argv[1]))
print(f"The alphabets size is {len(alphabet)}")
print(f"Security bits: {security}")

18
src/tasks/regex.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
import re
import sys
if len(sys.argv) != 2:
print("takes only a file path as argument")
exit(1)
textfile = open(sys.argv[1])
text = textfile.read()
regex = r"\b[a-z][AEIOUaeiou]([a-w]|[A-W])"
matches = re.finditer(regex, text, re.MULTILINE)
counter = 0
for i, match in enumerate(matches, start=1):
print(f"{i:03} | \"{match}\"")
counter += 1
print(f"found {counter}.")

1
src/tui/requirements.txt Normal file
View File

@ -0,0 +1 @@
terminaltexteffects==0.11.0

20
src/tui/tee.py Normal file
View File

@ -0,0 +1,20 @@
from terminaltexteffects.effects.effect_burn import Burn
text = """
Beautiful is better than ugly.
Explicit is better than implicit.
Beautiful is better than ugly.
Beautiful is better than ugly.
Beautiful is better than ugly.
Beautiful is better than ugly.
Beautiful is better than ugly.
Explicit is better than implicit.
Explicit is better than implicit.
Explicit is better than implicit.
Explicit is better than implicit.
Explicit is better than implicit.
"""
effect = Burn(text)
with effect.terminal_output() as terminal:
for frame in effect:
terminal.print(frame)