• Stars
    star
    231
  • Rank 173,434 (Top 4 %)
  • Language
    PHP
  • License
    MIT License
  • Created over 8 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

PHP library to handle IPv4, IPv6 and IP ranges

Tests Coverage Status Scrutinizer Code Quality Packagist Downloads Open in Gitpod

IPLib - Handle IPv4, IPv6 and IP ranges

Introduction

IPLib is a modern, PSR-compliant, test-driven IP addresses and subnets manipulation library. It implements primitives to handle IPv4 and IPv6 addresses, as well as IP ranges (subnets), in CIDR format (like ::1/128 or 127.0.0.1/32) and in pattern format (like ::*:* or 127.0.*.*).

Requirements

IPLib has very basic requirements as:

  • Works with any PHP version greater than 5.3.3 (PHP 5.3.x, 5.4.x, 5.5.x, 5.6.x, 7.x, and 8.x are fully supported).
  • No external dependencies
  • No special PHP configuration needed (yes, it will always work even if PHP has not been built with IPv6 support!).

Installation

Manual installation

Download the latest version, unzip it and add these lines in our PHP files:

require_once 'path/to/iplib/ip-lib.php';

Installation with Composer

Simply run

composer require mlocati/ip-lib

or add these lines to your composer.json file:

"require": {
    "mlocati/ip-lib": "^1"
}

Sample usage

Parse an address

To parse an IPv4 address:

$address = \IPLib\Address\IPv4::parseString('127.0.0.1');

To parse an IPv6 address:

$address = \IPLib\Address\IPv6::parseString('::1');

To parse an address in any format (IPv4 or IPv6):

$address = \IPLib\Factory::parseAddressString('::1');
$address = \IPLib\Factory::parseAddressString('127.0.0.1');

Get the next/previous addresses

$address = \IPLib\Factory::parseAddressString('::1');

// This will print ::
echo (string) $address->getPreviousAddress();

// This will print ::2
echo (string) $address->getNextAddress();

Get the addresses at a specified offset

For addresses:

$address = \IPLib\Factory::parseAddressString('::1');

// This will print ::1
echo (string) $address->getAddressAtOffset(0);

// This will print ::2
echo (string) $address->getAddressAtOffset(1);

// This will print ::3
echo (string) $address->getAddressAtOffset(2);

// This will print ::3e9
echo (string) $address->getAddressAtOffset(1000);

// This will print ::
echo (string) $address->getAddressAtOffset(-1);

// This will print NULL
echo var_dump($address->getAddressAtOffset(-2));

For ranges:

$range = \IPLib\Factory::parseRangeString('::ff00/120');

// This will print ::ff00
echo (string) $range->getAddressAtOffset(0);

// This will print ::ff10
echo (string) $range->getAddressAtOffset(16);

// This will print ::ff64
echo (string) $range->getAddressAtOffset(100);

// This will print NULL because the address ::1:0 is out of the range
var_dump($range->getAddressAtOffset(256));

// This will print ::ffff
echo (string) $range->getAddressAtOffset(-1);

// This will print ::fff0
echo (string) $range->getAddressAtOffset(-16);

// This will print ::ff00
echo (string) $range->getAddressAtOffset(-256);

// This will print NULL because the address ::feff is out of the range
var_dump($range->getAddressAtOffset(-257));

Parse an IP address range

To parse a subnet (CIDR) range:

$range = \IPLib\Range\Subnet::parseString('127.0.0.1/24');
$range = \IPLib\Range\Subnet::parseString('::1/128');

To parse a pattern (asterisk notation) range:

$range = \IPLib\Range\Pattern::parseString('127.0.0.*');
$range = \IPLib\Range\Pattern::parseString('::*');

To parse an address as a range:

$range = \IPLib\Range\Single::parseString('127.0.0.1');
$range = \IPLib\Range\Single::parseString('::1');

To parse a range in any format:

$range = \IPLib\Factory::parseRangeString('127.0.0.*');
$range = \IPLib\Factory::parseRangeString('::1/128');
$range = \IPLib\Factory::parseRangeString('::');

Retrieve a range from its boundaries

You can calculate the smallest range that comprises two addresses:

$range = \IPLib\Factory::getRangeFromBoundaries('192.168.0.1', '192.168.255.255');

// This will print 192.168.0.0/16
echo (string) $range;

You can also calculate a list of ranges that exactly describes all the addresses between two addresses:

$ranges = \IPLib\Factory::getRangesFromBoundaries('192.168.0.0', '192.168.0.5');

// This will print 192.168.0.0/30 192.168.0.4/31
echo implode(' ', $ranges);

Retrieve the boundaries of a range

$range = \IPLib\Factory::parseRangeString('127.0.0.*');

// This will print 127.0.0.0
echo (string) $range->getStartAddress();

// This will print 127.0.0.255
echo (string) $range->getEndAddress();

Format addresses and ranges

Both IP addresses and ranges have a toString method that you can use to retrieve a textual representation:

// This will print 127.0.0.1
echo \IPLib\Factory::parseAddressString('127.0.0.1')->toString();

// This will print 127.0.0.1
echo \IPLib\Factory::parseAddressString('127.000.000.001')->toString();

// This will print ::1
echo \IPLib\Factory::parseAddressString('::1')->toString();

// This will print ::1
echo \IPLib\Factory::parseAddressString('0:0::1')->toString();

// This will print ::1/64
echo \IPLib\Factory::parseRangeString('0:0::1/64')->toString();

When working with IPv6, you may want the full (expanded) representation of the addresses. In this case, simply use a true parameter for the toString method:

// This will print 0000:0000:0000:0000:0000:0000:0000:0000
echo \IPLib\Factory::parseAddressString('::')->toString(true);

// This will print 0000:0000:0000:0000:0000:0000:0000:0001
echo \IPLib\Factory::parseAddressString('::1')->toString(true);

// This will print 0fff:0000:0000:0000:0000:0000:0000:0000
echo \IPLib\Factory::parseAddressString('fff::')->toString(true);

// This will print 0000:0000:0000:0000:0000:0000:0000:0000
echo \IPLib\Factory::parseAddressString('::0:0')->toString(true);

// This will print 0001:0002:0003:0004:0005:0006:0007:0008
echo \IPLib\Factory::parseAddressString('1:2:3:4:5:6:7:8')->toString(true);

// This will print 0000:0000:0000:0000:0000:0000:0000:0001/64
echo \IPLib\Factory::parseRangeString('0:0::1/64')->toString();

The address and range objects implements the __toString() method, which call the toString() method. So, if you want the string (short) representation of an object, you can do any of the following:

$address = \IPLib\Address\IPv6::parseString('::1');

// All these will print ::1
echo $address->toString();
echo $address->toString(false);
echo (string) $address;

Check if an address is contained in a range

All the range types offer a contains method, and all the IP address types offer a matches method: you can call them to check if an address is contained in a range:

$address = \IPLib\Factory::parseAddressString('1:2:3:4:5:6:7:8');
$range = \IPLib\Factory::parseRangeString('0:0::1/64');

$contained = $address->matches($range);
// that's equivalent to
$contained = $range->contains($address);

Please remark that if the address is IPv4 and the range is IPv6 (or vice-versa), the result will always be false.

Check if a range contains another range

All the range types offer a containsRange method: you can call them to check if an address range fully contains another range:

$range1 = \IPLib\Factory::parseRangeString('0:0::1/64');
$range2 = \IPLib\Factory::parseRangeString('0:0::1/65');

$contained = $range1->containsRange($range2);

Getting the type of an IP address

If you want to know if an address is within a private network, or if it's a public IP, or whatever you want, you can use the getRangeType method:

$address = \IPLib\Factory::parseAddressString('::');

$type = $address->getRangeType();

$typeName = \IPLib\Range\Type::getName($type);

The most notable values of the range type are:

  • \IPLib\Range\Type::T_UNSPECIFIED if the address is all zeros (0.0.0.0 or ::)
  • \IPLib\Range\Type::T_LOOPBACK if the address is the localhost (usually 127.0.0.1 or ::1)
  • \IPLib\Range\Type::T_PRIVATENETWORK if the address is in the local network (for instance 192.168.0.1 or fc00::1)
  • \IPLib\Range\Type::T_PUBLIC if the address is for public usage (for instance 104.25.25.33 or 2001:503:ba3e::2:30)

Getting the type of an IP address range

If you want to know the type of an address range, you can use the getRangeType method:

$range = \IPLib\Factory::parseRangeString('2000:0::1/64');

// $type will contain the value of \IPLib\Range\Type::T_PUBLIC
$type = $range->getRangeType();

// This will print Public address
echo \IPLib\Range\Type::getName($type);

Please note that if a range spans across multiple range types, you'll get NULL as the range type:

$range = \IPLib\Factory::parseRangeString('::/127');

// $type will contain null
$type = $range->getRangeType();

// This will print Unknown type
echo \IPLib\Range\Type::getName($type);

Converting IP addresses

This library supports converting IPv4 to/from IPv6 addresses using the 6to4 notation or the IPv4-mapped notation:

$ipv4 = \IPLib\Factory::parseAddressString('1.2.3.4');

// 6to4 notation
$ipv6 = $ipv4->toIPv6();

// This will print 2002:102:304::
echo (string) $ipv6;

// This will print 1.2.3.4
echo $ipv6->toIPv4();

// IPv4-mapped notation
$ipv6 = $ipv4->toIPv6IPv4Mapped();

// This will print ::ffff:1.2.3.4
echo (string) $ipv6;

// This will print 1.2.3.4
echo $ipv6_6to4->toIPv4();

Converting IP ranges

This library supports IPv4/IPv6 ranges in pattern format (eg. 192.168.*.*) and in CIDR/subnet format (eg. 192.168.0.0/16), and it offers a way to convert between the two formats:

// This will print ::*:*:*:*
echo \IPLib\Factory::parseRangeString('::/64')->asPattern()->toString();

// This will print 1:2::/96
echo \IPLib\Factory::parseRangeString('1:2::*:*')->asSubnet()->toString();

// This will print 192.168.0.0/24
echo \IPLib\Factory::parseRangeString('192.168.0.*')->asSubnet()->toString();

// This will print 10.*.*.*
echo \IPLib\Factory::parseRangeString('10.0.0.0/8')->asPattern()->toString();

Please remark that all the range types implement the asPattern() and asSubnet() methods.

Getting the subnet mask for IPv4 ranges

You can use the getSubnetMask() to get the subnet mask for IPv4 ranges:

// This will print 255.255.255.0
echo \IPLib\Factory::parseRangeString('192.168.0.*')->getSubnetMask()->toString();

// This will print 255.255.255.252
echo \IPLib\Factory::parseRangeString('192.168.0.12/30')->getSubnetMask()->toString();

Getting the range size

You can use the getSize() to get the count of addresses this IP range contains:

// This will print 256
echo \IPLib\Factory::parseRangeString('192.168.0.*')->getSize();

// This will print 4
echo \IPLib\Factory::parseRangeString('192.168.0.12/30')->getSize();

// This will print 1
echo \IPLib\Factory::parseRangeString('192.168.0.1')->getSize();

Getting the reverse DNS lookup address

To perform reverse DNS queries, you need to use a special format of the IP addresses.

You can use the getReverseDNSLookupName() method of the IP address instances to retrieve it easily:

$ipv4 = \IPLib\Factory::parseAddressString('1.2.3.255');
$ipv6 = \IPLib\Factory::parseAddressString('1234:abcd::cafe:babe');

// This will print 255.3.2.1.in-addr.arpa
echo $ipv4->getReverseDNSLookupName();

// This will print e.b.a.b.e.f.a.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.c.b.a.4.3.2.1.ip6.arpa
echo $ipv6->getReverseDNSLookupName();

To parse addresses in reverse DNS lookup format you can use the IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS flag when parsing a string:

$ipv4 = \IPLib\Factory::parseAddressString('255.3.2.1.in-addr.arpa', \IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS);
$ipv6 = \IPLib\Factory::parseAddressString('e.b.a.b.e.f.a.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.c.b.a.4.3.2.1.ip6.arpa', \IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS);

// This will print 1.2.3.255
echo $ipv4->toString();

// This will print 1234:abcd::cafe:babe
echo $ipv6->toString();

You can also use getReverseDNSLookupName() for IP ranges. In this case, the result is an array of strings:

$range = \IPLib\Factory::parseRangeString('10.155.16.0/22');

/*
 * This will print:
 * array (
 *   0 => '16.155.10.in-addr.arpa',
 *   1 => '17.155.10.in-addr.arpa',
 *   2 => '18.155.10.in-addr.arpa',
 *   3 => '19.155.10.in-addr.arpa',
 * )
*/
var_export($range->getReverseDNSLookupName());

Using a database

This package offers a great feature: you can store address ranges in a database table, and check if an address is contained in one of the saved ranges with a simple query.

To save a range, you need to store the address type (for IPv4 it's 4, for IPv6 it's 6), as well as two values representing the start and the end of the range. These methods are:

$range->getAddressType();
$range->getComparableStartString();
$range->getComparableEndString();

Let's assume that you saved the type in a field called addressType, and the range boundaries in two fields called rangeFrom and rangeTo.

When you want to check if an address is within a stored range, simply use the getComparableString method of the address and check if it's between the fields rangeFrom and rangeTo, and check if the stored addressType is the same as the one of the address instance you want to check.

Here's a sample code:

/*
 * Let's assume that:
 * - $pdo is a PDO instance
 * - $range is a range object
 * - $address is an address object
 */

// Save the $range object
$insertQuery = $pdo->prepare('
    insert into ranges (addressType, rangeFrom, rangeTo)
    values (:addressType, :rangeFrom, :rangeTo)
');

$insertQuery->execute(array(
    ':addressType' => $range->getAddressType(),
    ':rangeFrom' => $range->getComparableStartString(),
    ':rangeTo' => $range->getComparableEndString(),
));

// Retrieve the saved ranges where an address $address falls:
$searchQuery = $pdo->prepare('
    select * from ranges
    where addressType = :addressType
    and :address between rangeFrom and rangeTo
');

$searchQuery->execute(array(
    ':addressType' => $address->getAddressType(),
    ':address' => $address->getComparableString(),
));

$rows = $searchQuery->fetchAll();
$searchQuery->closeCursor();

Handling non-standard address and range strings

Accepting ports

If you want to accept addresses that may include ports, you can specify the IPLib\ParseStringFlag::MAY_INCLUDE_PORT flag:

use IPLib\Factory;
use IPLib\ParseStringFlag;

require_once __DIR__ . '/../ip-lib.php';

// These will print NULL
var_export(Factory::parseAddressString('127.0.0.1:80'));
var_export(Factory::parseAddressString('[::]:80'));

// This will print 127.0.0.1
echo (string) Factory::parseAddressString('127.0.0.1:80', ParseStringFlag::MAY_INCLUDE_PORT);
// This will print ::
echo (string) Factory::parseAddressString('[::]:80', ParseStringFlag::MAY_INCLUDE_PORT);

Accepting IPv6 zone IDs

If you want to accept IPv6 addresses that may include a zone ID, you can specify the IPLib\ParseStringFlag::MAY_INCLUDE_ZONEID flag:

use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseAddressString('::%11'));

// This will print ::
echo (string) Factory::parseAddressString('::%11', ParseStringFlag::MAY_INCLUDE_ZONEID);

Accepting non-decimal IPv4 addresses

IPv4 addresses are usually expressed in decimal notation, for example as 192.168.0.1.

By the way, the GNU (used in many Linux distros), BSD (used in Mac) and Windows implementations of inet_aton and inet_addr accept IPv4 addresses with numbers in octal and/or hexadecimal format. Please remark that this does not apply to the inet_pton and ip2long functions, as well as to the Musl implementation (used in Alpine Linux) of inet_aton and inet_addr.

So, for example, these addresses are all equivalent to 192.168.0.1:

  • 0xC0.0xA8.0x0.0x01 (only hexadecimal)
  • 0300.0250.00.01 (only octal)
  • 192.0250.0.0x01 (decimal, octal and hexadecimal numbers)

(try it: if you browse to http://0177.0.0.0x1, your browser will try to browse http://127.0.0.1).

If you want to accept this non-decimal syntax, you may use the IPLib\ParseStringFlag::IPV4_MAYBE_NON_DECIMAL flag:

use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseAddressString('0177.0.0.0x1'));

// This will print 127.0.0.1
var_export((string) Factory::parseAddressString('0177.0.0.0x1', ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));

// This will print NULL
var_export(Factory::parseRangeString('0177.0.0.0x1/32'));

// This will print 127.0.0.1/32
var_export((string) Factory::parseRangeString('0177.0.0.0x1/32', ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));

Please be aware that the IPV4_MAYBE_NON_DECIMAL flag may also affect parsing decimal numbers:

use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print 127.0.0.10 since the last digit is assumed to be decimal
var_export((string) Factory::parseAddressString('127.0.0.010'));

// This will print 127.0.0.8 since the last digit is assumed to be octal
var_export((string) Factory::parseAddressString('127.0.0.010', ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));

Accepting IPv4 addresses in not-quad-dotted notation

IPv4 addresses are usually expressed with 4 numbers, for example as 192.168.0.1.

By the way, the GNU (used in many Linux distros), BSD (used in Mac) and Windows implementations of inet_aton and inet_addr accept IPv4 addresses with 1 to 4 numbers.

Please remark that this does not apply to the inet_pton and ip2long functions, as well as to the Musl implementation (used in Alpine Linux) of inet_aton and inet_addr.

If you want to accept this non-decimal syntax, you may use the IPLib\ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED flag:

use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseAddressString('1.2.500'));

// This will print 0.0.0.0
var_export((string) Factory::parseAddressString('0', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

// This will print 0.0.0.1
var_export((string) Factory::parseAddressString('1', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

// This will print 0.0.1.244
var_export((string) Factory::parseAddressString('0.0.500', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

// This will print 255.255.255.255
var_export((string) Factory::parseAddressString('4294967295', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

Accepting compact IPv4 subnet notation

Even if there isn't an RFC that describe it, IPv4 subnet notation may also be written in a compact form, omitting extra digits (for example, 127.0.0.0/24 may be written as 127/24). If you want to accept such format, you can specify the IPLib\ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT flag:

use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseRangeString('127/24'));

// This will print 127.0.0.0/24
echo (string) Factory::parseRangeString('127/24', ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT);

Combining multiple flags

Of course, you may use more than one IPLib\ParseStringFlag flag at once:

use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print 127.0.0.255
var_export((string) Factory::parseAddressString('127.0.0.0xff:80', ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));

// This will print ::
var_export((string) Factory::parseAddressString('[::%11]:80', ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID));

Gitpod Environment Variables

The following features can be enabled through environment variables that have been set in your Gitpod preferences.:

* Please note that storing sensitive data in environment variables is not ultimately secure but should be OK for most development situations.

  • Sign Git commits with a GPG key

    • GPG_KEY_ID (required)
      • The ID of the GPG key you want to use to sign your git commits
    • GPG_KEY (required)
      • Base64 encoded private GPG key that corresponds to your GPG_KEY_ID
    • GPG_MATCH_GIT_TO_EMAIL (optional)
      • Sets your git user.email in ~/.gitconfig to the value provided
    • GPG_AUTO_ULTIMATE_TRUST (optional)
      • If the value is set to yes or YES then your GPG_KEY will be automatically ultimately trusted
  • Activate an Intelliphense License Key

    • INTELEPHENSE_LICENSEKEY
      • Creates ~/intelephense/licence.txt and will contain the value provided
      • This will activate Intelliphense for you each time the workspace is created or restarted

Do you really want to say thank you?

You can offer me a monthly coffee or a one-time coffee 😉

More Repositories

1

docker-php-extension-installer

Easily install PHP extensions in Docker containers
Shell
3,855
star
2

php-cs-fixer-configurator

Inspect PHP-CS-Fixer fixers and easily configure them
TypeScript
206
star
3

powershell-phpmanager

A PowerShell module to install/update PHP, PHP extensions and Composer on Windows
PowerShell
199
star
4

gettext-iconv-windows

gettext and iconv binaries for Windows
VBScript
122
star
5

spf-lib

PHP library to parse, build and validate SPF (Sender Policy Framework) DNS records
PHP
49
star
6

betterpoeditor

Better PO Editor is an editor for .po files, used to generate compiled gettext .mo files which are used by many programs and websites to localize the user interface. It offers great features... It's worth to give it a try!
C#
40
star
7

ocsp

PHP library to query HTTPS Certificates revocation status using the Online Certificate Status Protocol (OCSP)
PHP
37
star
8

postcss

Unofficial PHP port of PostCSS
PHP
22
star
9

chm-lib

PHP library to read CHM (Microsoft Compiled HTML Help) files
PHP
21
star
10

concrete5-build

Helpful tools for concrete5
PHP
11
star
11

timezone-converter

Web app to convert date/time between different time zones
Vue
9
star
12

pecl-info

Info about PHP PECL packages
PHP
9
star
13

GestPay

PHP implementation of GestPay (Banca Sella)
PHP
9
star
14

incremental-git-filter-branch

A script that applies git filter-branch in an incremental way
Shell
7
star
15

my_boats

Sample concrete5 package to showcase ItemLists
PHP
7
star
16

jsgettext

Online tools to work with gettext .po, .mo and .pot files
TypeScript
7
star
17

composer-patcher

A Composer plugin to patch Composer packages.
PHP
6
star
18

concrete5-localizer

Package to allow localization of special items in concrete5.
PHP
6
star
19

mailup-php

A PHP class to manage communications with MailUp servers
PHP
5
star
20

tbfilters2gmail

A PHP library that allows you to parse Thunderbird rule files (msgFilterRules.dat) and easily export them to Google Gmail filters
PHP
5
star
21

idna

Library for International Domain Names (IDNA) 2008
PHP
5
star
22

warnings_log

concrete5 package to record all the PHP warnings (requires concrete5 8+)
PHP
5
star
23

mlocati.github.io

SCSS
5
star
24

concrete5-translations-updater

concrete5 package to update the translations of the core and of some package
PHP
5
star
25

check-php-syntax

A GitHub Action that checks if a directory contains PHP files with valid syntax
JavaScript
4
star
26

concrete5-translation-tools

Useful translations tools for concrete5
Python
3
star
27

ci-info

Retrieve CI (Continuous Integration) details
PHP
3
star
28

MLPosteDeliveryExpress

UNOFFICIAL C# library to use the Poste Italiane Delivery Express API
C#
3
star
29

CountryNames

PHP library to recognize localized country names thanks to Unicode CLDR
PHP
3
star
30

gdpr_cookie_notice

A concrete5 package to display a cookie-based notice (useful for GDPR purposes)
PHP
3
star
31

IMAP

A PHP library to fetch IMAP messages
PHP
3
star
32

concrete5-multilingual_attributes

Multilingual attributes package for concrete5
PHP
3
star
33

MediaData

Windows application to edit metadata (date/time and position/latitude-longitude-altitude) of images and videos
C#
2
star
34

localizable_doctrine_entities

Sample concrete5 package to showcase a way to localize Doctrine entities
PHP
2
star
35

concrete5-recaptcha

A package for concrete5 to enable reCAPTCHA captcha
PHP
2
star
36

concrete5-wrapper-script

POSIX and Windows shell scripts to run concrete5
Shell
2
star
37

concretecms-skeleton

The bare minimum structure for a ConcreteCMS installation with Composer
PHP
2
star
38

ab-gnuplot

An easy-to-use script to benchmark websites
PHP
2
star
39

libreoffice-uno-dotnet

LibreOffice + UNO + C#: issue with .Net but not with .Net Framework
C#
2
star
40

page_disabler

A concrete5 package to easily publish/unpublish pages with just 1 click
PHP
2
star
41

vat-lib

A PHP library to check VAT numbers
PHP
2
star
42

php-ide-extensions-helper

Generate fake PHP classes to help IDE autocomplete features
PHP
2
star
43

concrete5-deeply

A handy tool to view internal data of concrete5
PHP
2
star
44

audacity-fix-po

A Docker image that helps normalizing Audacity language files
Shell
2
star
45

automatic_image_rotator

Package for concrete5 5.6 to auto-rotate uploaded images
PHP
1
star
46

vba-json

Parse JSON strings in VBA (Visual Basic for Applications)
VBA
1
star
47

concrete5-versions-tester

Compare helpers, libraries, models, methods, functions and constants of any concrete5 version
JavaScript
1
star
48

true-for-windows

The most complicated C app ever written - For Windows
C
1
star
49

concrete5-eclipse-plugin

An Eclipse plugin for concrete5
Java
1
star
50

cloudfront_proxy_ip_provider

concrete5 package for proxy_ip_manager to support resolving CloudFront records
PHP
1
star
51

unipoints

A Unicode Codepoint library for PHP
PHP
1
star
52

cloudflare_proxy_ip_provider

concrete5 package for proxy_ip_manager to support resolving CloudFlare records
PHP
1
star
53

mlocati

1
star
54

comuni-italiani

A PHP library to work with Italian Regions, Provinces, and Municipalities
PHP
1
star
55

proxy_ip_manager

concrete5 package to manage the trusted proxy IP addresses
PHP
1
star
56

cname_proxy_ip_provider

concrete5 package for proxy_ip_manager to support resolving CNAME records
PHP
1
star
57

ADBMailer

C#
1
star
58

exiftool-translator

Translator utility for ExitTool, written in C#
C#
1
star
59

js-webcam-screenshot

Capture screenshots from webcam via JavaScript
JavaScript
1
star