Common CURL Parameters

Protocols
–http1.0 Use HTTP 1.0
–http1.1 Use HTTP 1.1
–http2 Use HTTP 2
-4 Resolve domain names to IPv4
-6 Resolve domain names to IPv6
-k Allow insecure connections in SSL
HTTP options
–data …HTTP POST data
–data-urlencode …HTTP POST data (‘@’ allowed)
-F name=content Specify multipart MIME data
-G Put POST data in URL and use GET
-H header/@file Pass custom header to server
–oauth2-bearer token Use OAuth2 bearer token
-u user:password Server user and password
–url URL to work with
Output
-D fileWrite received headers to file
-fFail silently on HTTP errors
-i Include response headers in output
-o file Output to file name
Mode
-LFollow redirects
-sSilent mode
-vVerbose

My List of Ubiquitous Software

(Really just a list for myself when I reinstall a new computer.)

Productivity

Communication

  • Skype – but the Windows client, not the Win10 app
  • Slack – collaboration/chat client

Development

Tools & Utilities

Internet

Security

Audio

Graphics

  • Inkscape – SVG editor
  • Corel Paint Shop Pro 9 – pretty good image editor, fast, lightweight, but only version 9
  • NAPS 2 – scanner utility

Video

Servers

  • Apache/PHP – web server (links to Windows downloads)
  • MySQL – still my favorite database
  • Zabbix – server monitoring, takes a while to set up right but when it works, it’s nice
  • OpenHAB 2 – IoT automation and monitoring (a real pain to set up right, but powerful when it works)
  • Bitvise SSH Server – free Windows ssh server
  • RabbitMQ – messaging platform

Common wget Parameters

-oOutput file name
-ncNo-clobber (don’t overwrite anything)
-cContinue (add to existing file)
-NOnly retrieve if newer than existing
-SDisplay server response
-nHDon’t create host directories
–header=xInsert custom header
–save-headersSave headers to file
–referer=x Use custom referer
–method=xUse custom HTTP method
–post-data=STRSet POST data from string
–post-file=FILESet POST data from file
-rRecursive
-l nMaximum recursion level
-kConvert links to local
-pPage requisites
-LFollow relative links only
-npNo-parent (don’t ascend into parent directory)

Password Management Survey Results

(Please scroll to the bottom to see a few simple password recommendations and guidelines.)

A week or two ago, I sent out a request on Facebook and LinkedIn for people to participate in my survey about password management. My interest was to see, given how complex passwords are becoming and how easy it really is to crack most passwords, how people on various technical levels approach password management.

I did get a handful of responses – not overwhelming by any means, but still enough to put together a survey result, which I think is interesting to analyze. The initial results confirmed my suspicions that there is a discernible divide between people who rated themselves “high” on an IT competence scale (security experts, software developers, people who have to manage IT security) and “low” (at-home users or people who get exposed to security issues at work).

Let’s dig in.

1. How do you manage passwords?

Most people use either a few passwords for all their needs, or rely on an online manager to remember their passwords. What’s interesting is the divide between higher or lower IT competence – people who manage computer security need more complex passwords and use password managers to remember their passwords, while everyday users use a few lower-complexity passwords to get around.

We’re really today at the point where some kind of manager is necessary – with widespread hacks of online services and multi-million password dumps on the internet, it is no longer viable to use a single password or a few – the recommendation is to use a different one for every website you visit, and no one can remember those.

At a minimum, email accounts, social media accounts, and financial/bank accounts must have separate, individual passwords.

It’s also interesting to note the low score of Google/Facebook sign-in responses. They both provide a fully functional trust mechanism to authenticate yourself online, but seem unpopular for some reason.

2. Two-factor authentication

On the lower end of IT competence, most users responded that they did not know what 2FA (two-factor authentication) was. On the higher end, the trend was to secure a few accounts with 2FA (presumably the most important ones).

Two-factor authentication means that not only do you have a password to secure your account with, you’re also sent login codes through SMS, or more preferably these days, an authentication software such as Google Authenticator.

My guess is that most people are not aware of why this is necessary, and perceive it as an unnecessary complexity. However, given the fact that with someone’s email account, you can usually recover a major portion of the passwords from every other website, securing your email and social media accounts with SMS codes or app verification is absolutely vital.

3. Online banking authentication methods

Because I wanted full anonymity, I disabled IP address tracking in my survey; however, that also meant I lost the capability to check the origin country of the survey results, which would have been interesting.

It seems largely evenly split between using some kind of authentication service (Bank-ID was mentioned in the options) and using passwords with security questions.

My guess is that it’s rather evenly split between U.S. banks and Swedish banks. U.S. banks typically use passwords with security questions (which is rather behind the curve and poor security for banks), while Swedish banks rely on the BankID infrastructure – which is much more cryptographically secure.

An increasing trend seems to be sending security codes with email or text messaging – which is already outdated and once again proves the absolute necessity of securing your email account – and very few rely on one-time passwords (codes written on paper), which is highly secure but pose more cost and complexity in administration.

4. Password recovery

The most interesting divide between users with higher IT competence and not is the method to remembering or recovering passwords. IT professionals mostly use passwords stored online, while common users rely more on their memory. Unfortunately the human mind is not suited well to remembering complex passwords – the more random, the better, and the mind wants to remember patterns which can easily be exploited.

An interesting point is that so many rely on online password storage, while very few rely on offsite storage. The danger, of course, with online storage is that you also rely on the protection mechanisms of the online provider – and should that get breached, your entire online life is fully and completely exposed.

5. Password complexity

As expected, most common users rely on variations of word patterns, with capitalization and the odd digit thrown in. As IT security competence increases, so does password complexity, and it’s good to note that security professionals are trending towards full randomization of passwords with included punctuation. While horribly difficult to remember and in some cases to type in, one would assume that these passwords are protecting administrative accounts to a larger extent, which could exponentially increase the severity of a hack.

However, there is still a firm reliance on using words as passwords. Given that the English language has about 250,000 words; and a modern, GPU-powered password cracker can easily try 100 million passwords per second on lower-complexity password hashes; using variations of words is becoming increasingly dangerous.

With proper security implementations – for instance, using salted bcrypt/scrypt hashes or similar for password storage – trying brute-force attacks on passwords should be infeasible; but as we’ve so often seen, developers frequently use poor hashes to store passwords – or even storing them as plain text.

The danger here is that if one password is used for many websites, it only takes one breakthrough on a poor-security website to access the password, and hackers can then move laterally through different systems in the search for deeper security access.

6. Training

I added this question to gauge the interest in either online videos or local classes when it comes to computer security. Among the people responding, almost half would be interested in watching an online video, while the rest felt that they did not need training or that they already knew enough. There was a trend among security professionals to not be interested (because they already knew enough), but not completely.

Perhaps it would be interesting to put together a training video and see if it’s possible to educate people on online security and password management. I have to wonder if I’m the best instructor, though, since I rely on KeePass for offline password storage and other rather complex mechanisms… ūüôā

Final thoughts and recommendations

It is clear to me that passwords have outlived their usefulness, and that we’re heading for authentication tokens instead – long, cryptographically complex strings that allow us to access resources and identify us with – which are, of course, impossible to memorize but can easily be handled by computers.

However, the infrastructure today doesn’t really exist. In the meantime, online password management seems to be a clear trend, and with each cell phone iteration we’re looking at more biometric security systems… which have the unfortunate drawback that once they’re hacked, it’s practically impossible to change the biometric signature (your iris or fingerprint).

My short recommendations are as follows:

  • Use different passwords for every website.
  • Use the password memory feature of your web browser (Firefox, Google Chrome) to remember the passwords. It’s a good idea to enable synchronization – the web browser should be doing that automatically if you’re logged in to it.
  • You may also want to look into password managers – LastPass, 1Password and others are popular. If you have the skill to do so, you may want to use an offline manager such as KeePass or KeePassX – but do take backups!
  • For higher-value websites, such as email, social media and financial institutions, do enable 2-factor authentication if at all possible.
  • For banks or any other websites which can have dramatic life implications if they get hacked, avoid letting any web browser store the password. Use a good password manager or write it down somewhere out of sight.

For work users, it’s very important to stay vigilant, follow the work security policy and keep the rules above in mind. Surprisingly often, hackers gain entry to a high-value target by hacking a regular user and then moving laterally through the inside systems, looking for further security weaknesses to exploit.

Thank you for participating!

Steps to Greater Happiness and Fulfilment of Joy with Dropbox and KeePass

I use Dropbox and KeePass together to manage all my passwords; for websites, email accounts, PIN codes and everything else. I use KeePass because I don’t trust online services to store my passwords for me; I want them at home, private, where only I can see them and no one else. However, it takes a little bit of effort to set this up – but it’s well, well worth it. Here’s how I do it:

Set up Dropbox

  1. Install Dropbox from https://www.dropbox.com/install.
  2. If you do not have an account, sign up for an account with your email address. Otherwise, log in. If you do not remember your password, set a new password using the account recovery mechanism (click on “forgot your password”).
  3. You should now have access to your Dropbox account, and there should be a Dropbox folder on your computer, which you can access either by double-clicking on the Dropbox icon in the system tray (or the desktop), or by navigating to the dropbox folder using the regular file access views in Windows (so called Windows Explorer).
  4. If you want to change the location of the Dropbox folder, you may do so by doing the following. This is an optional step and is not necessary, but can be useful if you want your files in a different location.
    • Click on the Dropbox icon in the system tray
    • When the little window appears with Dropbox notifications, click on the cogwheel in the upper right part and select Preferences.
    • Select the Sync tab in the Dropbox Preferences¬†window.
    • Click the Move¬†button under Dropbox folder location¬†at the bottom.
    • Select a folder on your computer where you want the Dropbox folder to reside. Do not include the actual “Dropbox” in the folder name; if you want the dropbox folder to be D:\Dropbox, just select D:\¬†as the location – this is useful if you have two hard disks and want the dropbox files on the second hard disk, separated from the system drive.
  5. I also recommend putting your Desktop inside the Dropbox folder, so everything on the desktop is automatically backed up. Usually people put a lot of things on the desktop, and it’s good to have that backed up. The downside is that everything on the desktop will have a little green check-mark on it, but it’s well worth it. (This applies to Windows 10, specifically, but probably works in other Windows versions too.)
    • First of all, in the Dropbox folder, create a new folder somewhere called Desktop. It can be anywhere; I like to create a folder called sys or system¬†and underneath that one keep things like the desktop folder, and so on, so I keep them separated.
    • Open the File Explorer (or just about any folder on your computer works too).
    • On the left, you should have a list of folders, like Desktop, Downloads, Documents, Pictures and so on. Right-click on Desktop¬†in this list, and select Properties.
    • Click on the Location¬†tab, and click on Move. Navigate to the new folder you created for the desktop in the Dropbox folder and click Select Folder; verify that the dialog box now shows you the new desktop folder in Dropbox, and click OK.
    • All of your desktop files should now be synchronizing with Dropbox.

Set up KeePass

  1. Now we’re going to set up KeePass. If you don’t have KeePass, download it from https://keepass.info/download.html and set up a password database as needed. Please choose the Installer for Windows¬†and the most recent version (2.x something).
  2. Install the program, and create a new database. Be sure to have a good, strong password; something like “I always eat 52 pizzas!” Don’t make it too long – you have to type it in on your phone as well. (Of course, if you already have a password database from before, simply move it inside the Dropbox folder and make sure it gets the little green check-mark on it.)
  3. Add a few passwords for good measure. Save the file somewhere in Dropbox.
  4. After this, it might be a good idea to head over to the menu option File > Database Settings in KeePass, and look under the Security tab for Iterations. Increase the number significantly (to at least 100,000) and use the Test button to find a number that results in about ~0.1 seconds. This is a computing-intensive step that will harden access to your database and make it utterly impractical to run brute-force passwords crackers against it. (Bear it mind that your cell phone may not have the computing capacity of your computer, and will likely take a little longer to open the database. 0.1 seconds should be good.)
  5. Once again, make sure the KeePass database is saved inside the Dropbox.
  6. You should now be able to access the password database from anywhere, as long as you have access to your Dropbox account and a KeePass program that can read it. Please do not do so from any computer you don’t absolutely trust, as the data stored in the password database is a gold-mine for criminals.

Accessing the KeePass database from your Android phone

  1. To access the password database from your Android phone, start by installing Dropbox on your phone, and log in. Make sure you can see your files.
  2. Open the Play Store and install KeePassDroid by Brian Pellin.
  3. Now, go back to Dropbox, and navigate to your password database. Click on the little menu icon (the three dots) on the right side of the password file. Select Available offline. Your password database should now automatically be available offline and visible under the Offline files section in the Dropbox main menu.
    • Please note that Dropbox will not automatically synchronize it unless you actually open Dropbox. For this reason, the recommended way to access the file is to go through Dropbox – this will ensure that it’s properly updated before you use it.
    • It is possible that there are better alternatives than Dropbox – someone mentioned DropSync. I have no experience with this.
  4. Now, by clicking on the password file in the Dropbox offline section, KeePassDroid should automatically open. (If it doesn’t, try “Open With”.) Enter the password, and behold the glory and joy of having all your passwords instantly accessible on your phone, and yet securely.
    • I try to only use the computer to actually update or change the passwords; I’m not 100% confident that those Android apps will make changes to the password database without problems. If there’s anything you don’t want, it’s a corrupted password database.

That should be it.

Aggregated Fail States

The concept of a program failure, in the mind of a software developer, usually takes the form of a boolean or an exception. It’s either true or false, fail or no-fail.

But sometimes you come across more subtle error states – and this is especially true with web-based applications or applications that consume external services. Temporary errors, due to connectivity issues, pop up from time to time, and handling those correctly means the program has to have some sense of whether the error is temporary, localized, important-enough-to-abort, and handle multiple errors at the same time.

Collecting data from Facebook API’s, for instance, can result in most calls succeeding, but one or two failing. Maybe Facebook deprecated a particular metric. Maybe there’s packet loss on the way. Maybe there’s a slight temporary error… and sometimes there are just hard failures (like authorization failures where access tokens have expired).

I am moving to something I call a ResultState. It’s a simple class that looks something like this:

    public class ResultState
    {
        public bool Success { get; set; }
        public bool Finished { get; set; }
        public int TryCount { get; set; }
        public List<LogEntry> Messages { get; } = new List<LogEntry>();

        public bool Retry(int maxAttempts)
        {
            Finished = TryCount++ >= maxAttempts;
            Success = false;
            return !Finished;
        }

        public void Set(bool successful, LogEntry message = null)
        {
            Finished = true;
            Success = successful;
            if (LogEntry != null)
                Messages.Add(LogEntry);
        }
    }

It’s a simple class I’m using in a Batch Call function – every request inside a batch request is capable of being successful, not successful, or unfinished (retrying). The Batch Processor will keep submitting the request to the external API until all calls are complete – whether they ended in a failure or not.

    // Run batch request
    do {
        ...
    } while (!batchItems.All(x => x.Finished));

    // Dump messages to application log
    Logger.Write(batchItems.SelectMany(x => x.Messages).ToList());

The important thing is to constantly be able to feed upper-level methods with a “state” – the LogEntry object carries a descriptive message along with a severity code that allows the main process to evaluate the severity of the situation and take appropriate action. Indeed, from the Batch request it receives a List that describes all the various states and errors that were returned. It runs a Distinct() on these to feed the end result to the user.

For headless operations (where a process runs activities in the background), there are several consumers of ResultStates that might be interesting:

  • Upper-level methods and diagnostic software that must act on the information.
  • System operators, responsible for monitoring and debugging the software.
  • End users that are interested in the result of the operation, and need to know when or why things are failing.

Nothing is worse than running an automated job and receiving no response whatsoever whether it failed or ran successfully. And nothing is more frustrating than to receive a simple “failed” status back without any indication as to why. Aggregated fail states that can bubble up messages from individual methods are necessary in communicating just what happens, and why. Ideally, a system operator should be able to investigate the failure by just looking at easily accessible web-based logs.

Windows CMD reference

I spent a part of yesterday looking through all the commands in Cmd.Exe (the Windows command shell, inheritor of the old COMMAND.COM). It’s interesting how they’ve added switches and stuff to improve on it since the early days, but how almost nobody seems to use it. Admittingly, it’s a far cry from bash, the Unix command shell, but there’s a few old tricks you still can pull out of the hat. People may flame it and despise it, but I always thought you should be able to do more with the good ol’ shell.

Here’s a few of the things I found … in alphabetical order.

ATTRIB [/s] [/d]

Changes file attributes. /s makes it recursive, /d makes it operate on directories as well. I didn’t know about these switches before. Handy.

CALL :label arguments

Neither did I know you could call a label in a batch file. This should make it easier to write “gosub”-like routines. And the parameters can be expanded with new interesting features, see below. To exit from the subroutine, use the “goto :eof” statement.

CHKNTFS

Schedule a check-disk on next boot. Might come in handy sometime.

EXIT /b [errorlevel]

Exits the command shell. If you use the /b switch, exits the current batch file. You can also pass an errorlevel along.

F7

Pressing F7 brings up the history list. How come I never knew that?

FINDSTR [/r] [/c:]”search string” filespec

Find strings in files. I might still use Turbo Grep, but this is cool too. Normally it searches using an OR pattern on the search string (meaning “I love you” finds all instances of “I”, “love” or “you”), use the /c: switch to make it an AND search.

The /r parameter turns the search string into a regexp. Note, some of the fancier stuff might not work as usual, consult the FINDSTR /? or the online help for further information.

FOR %%v IN (set) DO …

The FOR command is one of the coolest features in batch programming. I had no idea you could do so much with it.

FOR %%f IN (dpr pas dfm res) DO COPY *.%%f \deploy

Copy all Delphi source files for a project to a specific directory.

FOR /d %%d IN (set) DO ...

Match directories in wildcards instead of files.

FOR /r [path] %%v IN (set) DO ...

Recursive operation on files found, optionally operating relative to “path” instead of the current directory. It might be used like “FOR /r c:\deploy %%f IN (*.*) DO ATTRIB -r %%f”, which will recursively remove the read-only attribute from all files in c:\deploy.

FOR /l %%v IN (start, step, end) DO ...

For-loop. “FOR /l %%v IN (1, 1, 5)” gives the sequence 1 2 3 4 5.

FOR /f ["options"] %%v IN (file-set | "string" | 'command') DO ...

The /f parameter is probably the most interesting feature I’ve found. It reads lines from an input file, string, or result from a shell command, tokenizes them and processes a command for each line. Normally, the token delimiters are space and tab, and it usually operates on the first token found, so without extra options you will always get the first word in each line. But it can be modified with the following options:

eol=c             Set the end-of-line character. One character only.
skip=n            Skip n lines in the beginning.
delims=xxx        Delimiter set, default is space and tab.
tokens=x,y,n-m    Which tokens to feed into the command. Variables start at the variable 
                  given, and allocates further as needed in alphabetical order. * means
                  "the rest of the line".
usebackq          Use backticks instead of apostrophe for the command evaluation. The 
                  format changes to ("file-set" | 'string' | `command`). Required if you 
                  use filenames with spaces.
FOR /f "eol=; tokens=2,3* delims=, " %%i IN (myfile.txt) DO @ECHO %%i %%j %%k

Parse each line in myfile.txt, ignoring lines that begin with semicolon, pass 2nd and 3rd tokens into the command, separating each token my either comma or space. Notice how the sequence goes: %i, %j, %k.

FOR /f "usebackq delims==" %%i IN (`set`) DO @ECHO %%i

Enumerate all variables found.

Expansion of variable parameters is also available, see below.

GOTO :eof

Jump to end of file. Handy way of exiting from a script.

IF comparisons

IF [NOT] ERRORLEVEL n ..
IF [NOT] EXIST filename ...
IF [NOT] string1==string2 ...
IF [/i] string1 EQU|NEQ|LSS|LEQ|GTR|GEQ string2 ...

The normal IF command is enhanced, too. It can check errorlevels as before, file existance, and compare strings. But is also has new operators. For instance, the “IF ERRORLEVEL 3” statement can now be written “IF %ERRORLEVEL% LEQ 3”.

/i means case-sensitive (or case-insensitive, I forgot which). Numeric strings evaluate as numbers, not strings.

IF now also supports multi-line statements and ELSE statements, see below.

MD \a\b\c\d

Will create new directories in sequence.

MORE /e

Extended more. These keys are available:

P n     - next n lines
S n     - skip n lines
F       - next file
Q       - quit
=       - show line number
?       - show help line
space   - next page
return  - next line

MORE +n

Start from line n.

PUSHD \\server\path

Create a temporary drive allocation, starting from Z:, for the particular UNC path. This will be cleared with POPD.

RD /s /q

Very dangerous command.

SET

SET [var[=[value]]]
SET /a [var=]expression
SET /p var=[prompt]

SET only will display all variables. SET P will display all values starting with P. SET P= will clear variable P.

SET /a will perform a calculation, for instance SET /a X=2*2 + 5.

SET /p will prompt for user input and store the result in a variable.

SETLOCAL / ENDLOCAL

Make local changes to the environment. Work all you want with it, then call endlocal to revert back to where you were. Also handy, especially with some of the advanced SET features.

SHIFT [/n]

Shift parameters. Optionally start at the nth position, preserving all elements %0 .. %(n-1).

SORT [/+n] [/o outfile]

Sort may start sorting at the nth position now. Could be good for unwanted stuff in the beginning (timestamp in logs, perhaps). /o is faster than piping.

Interesting ways of treating variable expansion

Some new ways of treating variables are available. Like, string substitution and substring matching.

%PATH:str1=str2%      Substitute all occurrences of str1 with str2.
%PATH:~10,5%          Substring, start at position 10 and extract 5 characters.
%PATH:~-10%           Only get the last 10 characters.
%PATH:0,-2%           Extract all but the last 2 characters.

%CD%                  The current path
%DATE%                Current date
%TIME%                Current time
%RANDOM%              A random number between 0..32767.
%ERRORLEVEL%          The current errorlevel.

%*                    All arguments
%0 .. %9              Arguments
%~1                   Remove quotes from parameter 1
%~f1                  Expand to fully qualified filename
%~d1                  Expand to drive letter only
%~p1                  Expand to path only
%~n1                  Expand to file name only
%~x1                  Expand to extension only
%~s1                  Expand to short file name only
%~a1                  Expand to file attributes
%~t1                  Expand to file date/time
%~z1                  Expand to file size
%~$PATH:1             Search through all directories specified in %PATH%. If the file is found,
                      return the fully qualified filename in that directory. If the file isn't 
                      found, return blank.
%~dp1                 Expand to drive and path. (Further elements may be combined: 
                      %~ftza1 gives a DIR-like output)

Interesting ways of doing IF and FOR statements

There’s a syntax I’ve never seen either with IF and FOR statements. You can use IF-ELSE-syntax in this way:

IF EXIST hello.txt (
    DEL hello.txt
) ELSE (
    ECHO hello.txt is missing!
)

…or even…

IF EXIST hello.txt (DEL hello.txt) ELSE (ECHO hello.txt is missing!)

And how about this?

FOR /l %%v IN (1 1 5) DO (
    ECHO This is line number %%v.
)

The crucial thing seems to be, in ELSE statements, that ELSE has to be written “on the same line” as the IF statement. This is why ELSE is written on the same line as the parantheses.

So there you are. A whole new way of writing batch files. No extra software needed, just plain old Windows XP.

MySQL Function to Calculate Excel-style Dates

drop function if exists exceldate;

delimiter //

-- Function that returns an Excel-style or Delphi-style date value
-- from a MySQL date. A date value of 0 represents 1899-12-30.&lt;/em&gt;
create function exceldate(p_date date)
    returns int
    sql security invoker
begin
    return to_days(p_date) - 693959;
end //

delimiter ;

select '1899-12-31', exceldate('1899-12-31') -- should be 1
union
select '2011-10-18', exceldate('2011-10-18'); -- should be 40834

Luhn (mod 10) Check Digit Algorithm in MySQL

drop function if exists luhn;
drop function if exists luhn_check;

delimiter //

-- Function that calculates a Luhn (mod 10) check digit from a numeric string.
-- The behavior is undefined if the string contains anything else than digits.
-- Assumes that the string does not have a check digit added yet, so it starts
-- with a weight of 2 at the last digit.
create function luhn(p_number varchar(31))
    returns char(1)
    sql security invoker
begin
    declare i, mysum, r, weight int;

    set weight = 2;
    set mysum = 0;
    set i = length(p_number);

    while i > 0 do
        set r = substring(p_number, i, 1) * weight;
        set mysum = mysum + if(r > 9, r - 9, r);
        set i = i - 1;
        set weight = 3 - weight;
    end while;

    return (10 - mysum % 10) % 10;
end //

-- Check if a numeric string has a valid check digit. Does this by cutting off
-- the last digit, recalculating the Luhn check digit, and comparing the strings.
create function luhn_check(p_number varchar(32))
    returns boolean
    sql security invoker
begin
    declare luhn_number varchar(32);
    
    set luhn_number = substring(p_number, 1, length(p_number) - 1);
    set luhn_number = concat(luhn_number, luhn(luhn_number));
    
    return luhn_number = p_number;
end //

delimiter ;

Common ffmpeg parameters

Information

-codecsDisplay codecs
-formatsDisplay formats
-f fmtForce format “fmt”
-i filenameSet input file name
-yOverwrite output file
-t secsForce duration to specific length (hh:mm:ss[.xxx])
-fs limitSet file size limit
-ss secsSeek to given time position (hh:mm:ss[.xxx])
-target typeSpecify target type (“vcd”, “svcd”, “dvd”, “dv”, “dv50”, “pal-vcd” etc); all format options are set automatically
 

Video

-b bitrateVideo bitrate in bps
-r fpsSet frame rate (default 25)
-s WxHSet frame size (default same as source)
-vf scale=W:HRescale video (use <=1 to scale, e.g. “640:-1” means resize height to scale, -2 means same but maintain even /2 count)
-vf transpose=nRotate video (0 = 90¬į counterclockwise and vertical flip; 1 = 90¬į clockwise; 2 = 90¬į counterclockwise; 3 = 90¬į clockwise and vertical flip)
-aspect aspectSet aspect ratio (4:3, 16:9 etc)
-vnDisable video
-pass nMultipass rendering (1 or 2)
-vcodecForce video codec (e.g. “h264”, “copy”)
-crf nnConstant Rate Factor (0=lossless, 23=default, 17-28=acceptable)
 

Audio

-ar freqAudio frequency (default 44100 Hz)
-ab bitrateAudio bitrate in bps (default 64k)
-aq qualityAudio quality (codec-specific, VBR)
-ac channelsAudio channels (ac=2 to downmix 5.1 to stereo)
-anDisable audio
-acodec Force audio codec (“aac”, “mp3”, “copy”)
 

Subtitles

-scodecForce subtitle codec (“copy” to copy stream)
-snDisable subtitles