This issue plagued me for ages.
When i printed from Firefox either directly or by creating a PDF (via cutePDF), the output was scaled to about 25% of normal size making the printouts unusable.
The percetage reduction is just a guidline as there can be some variation, but the outcome is always a smaller version of what you want.
Solution
In Firefox page setup:
No need to re-flash the rom. You can change it from 'Home screen settings'.
This article will outline some basic steps to increase the security of cPanel and reduce SPAM but only as an end user. This is not targetted at people who have access to the server, but they can use this information.
Enable the following services:
Enable the following services:
These are my instructions to install LEDE on a Virtualbox virtual machine so i can play around with various setups and add-ons without breaking my router. I am a windows user, so these instructions are windows based but a lot should be the same. Through this guide I will use 'VB' which is instead of typing virtualbox virtual machine lots of times.
Download and install VirtualBox before anything else.
These instructions are a companion to LEDE Project: Run LEDE as a Virtualbox virtual machine which has some errors in it.
This is can be confusing so I will outline what the different types are below. The image files are also specific to certain chips or technology, so in this case these images are for x86/x64 archeitectures. The Stable Releases are also sorted by their release number, so make aure you always get teh latest version.
The 2 files to choose from will have filenames similiar to these which are from the 17.01.4 stable release folder.
I have chosen to use lede-17.01.4-x86-64-combined-ext4.img.gz because I can easily expand the ext4 storage partition.
Notes
Make the VirtualBox VDI file
Run the following command in the directory you have your LEDE image file.
"C:\Program Files\VirtualBox\VBoxManage" convertfromraw --format VDI lede-17.01.4-combined-ext4.img lede-17.01.4-combined-ext4.vdi
Now skip to the section Make the Virtualbox Virtual Machine.
Make the VirtualBox VDI file
Run the following command in the directory you have your LEDE image file.
"C:\Program Files\VirtualBox\VBoxManage" convertfromraw --format VDI lede-17.01.4-x86-64-combined-squashfs.img lede-17.01.4-x86-64-combined-squashfs.vdi
Converting the img file to a VDI file fails with an error
When you try and convert an untouched lede-17.01.4-x86-64-combined-squashfs.img to a virtualbox VDI file using VboxManage you will always get an error similiar to the one below:
D:\>"C:\Program Files\VirtualBox\VBoxManage" convertfromraw --format VDI lede-17.01.4-x86-64-combined-squashfs.img lede-17.01.4-x86-64-combined-squashfs.vdi Converting from raw image file="lede-17.01.4-x86-64-combined-squashfs.img" to file="lede-17.01.4-x86-64-combined-squashfs.vdi"... Creating dynamic image with size 19852146 bytes (19MB)... VBoxManage.exe: error: VD: The given disk size 19852146 is not aligned on a sector boundary (512 bytes) VBoxManage.exe: error: Error code VERR_VD_INVALID_SIZE at F:\tinderbox\win-5.1\src\VBox\Storage\VD.cpp(7002) in function int __cdecl VDCreateBase(struct VBOXHDD *,const char *,const char *,unsigned __int64,unsigned int,const char *,const struct VDGEOMETRY *,const struct VDGEOMETRY *,const union RTUUID *,unsigned int,struct VDINTERFACE *,struct VDINTERFACE *) VBoxManage.exe: error: Cannot create the disk image "lede-17.01.4-x86-64-combined-squashfs.vdi": VERR_VD_INVALID_SIZE D:\>
Explanation
This simple to explain. The image file is only 19MB in size but represents a drive that is nearly 300mb in size (16mb + 256mb). VboxManage parses the img file and sees a 300mb file system so it expects a file that is 300mb long, but because the file is not 300mb long as expected VboxMan returns an error. This is basically an unexpected end of file error. VboxMan actually interprets the files system in the file which is stored at the beginning so this error is expected.
NB: the img file does not need to be 300mb in normal circumstances because if you image the file 'as-is' onto a large enough drive then you would not have this issue because the OS would just see the extra space dues tot he partition table being correct. This keeps the file size to the absolute minimum. We only change the image because we want to create a virtual drive from the img and this process like validate partions and files systems so it can convert them to its own format.
Research / Examples
Look at these 2 examples where I have padded the files with 100mb and 300mb respectively, converted them to a VDI image, loaded them in the LEDE virtual machine and then booted with Gparted to see what was going on with the disks.
The 100mb example has an error that come up before you even get the disk map.
This error actually appears twice, I am guessing that is because there are 2 partitions.
Now as you know is not possible to fit the sda2 256mb partition onto a hard disk that is only 100mb in size. . The 100mb drive is likely to be corrupted or cause many issues.
So I now move on to where I padded the image file with 300mb.
You can see the whole partition sda2 is within the drive boundries so will be healthy. VboxManage considers the whole file size when creating a VDI file. Both the 100mb and the 300mb VDI files were 9,216kb exactly so there must only be a slight difference in a setting controlling the virtual hard drive size.
NB: I do not know why the file system is unknown.
Padding the file
Now we know what the issue is we can fix it. We do this by making the file 300mb in size using the linux command dd. This allows us to extend the length of the file without affecting the contents that are already there.
You need a Linux system to be able to run the following commands. If you are on windows there is section below briefly telling you how to setup an Ubuntu virtual machine.
This command is wrong (from LEDE Project: Run LEDE as a Virtualbox virtual machine )
dd if=lede-17.01.4-x86-64-combined-squashfs.img of=lede.img bs=128000 conv=sync
Use this command
dd if=lede-17.01.4-x86-64-combined-squashfs.img of=padded-lede-17.01.4-x86-64-combined-squashfs.img bs=300M conv=sync
We now have a file that will convert
Run the following command in the directory you have your padded img file to create your virtual hard drive VDI file.
"C:\Program Files\VirtualBox\VBoxManage" convertfromraw --format VDI padded-lede-17.01.4-x86-64-combined-squashfs.img lede-17.01.4-x86-64-combined-squashfs.vdi
Notes
This is a workaround for windows users to be able to use the dd command. There must be a windows equavalent but I don't know of one at the minute so here are my instructions to setup an Ubuntu virtual machine.
I used an Ubuntu 17.10 Artful (Final) Virtualbo prebuilt image from http://www.osboxes.org/ubuntu/
Credentials
Create the VB Machine
Configure the VB
Ubuntu is now running but we need to get the image files into the installation so there are a few settings that need to be configured to amke this an easy process.
Pad the file
You can now access your Ubuntu install by using \\osboxes
Notes
Follow the instructions below
I never got this to work (resizing sda2) but I did a lot of looking on the internet and here are the links I collected.
Extroot
The virtual hard disk is split into 2 partitions, 16mb system and a 256mb data partition. For most people this should be enough however if you want more space follow these instructions which are best done before you start playing with your LEDE install bu you can do this later if you want.
Increase the capacity of the virtual hard drive
"C:\Program Files\VirtualBox\VBoxManage" modifymedium lede-17.01.4-combined-ext4.vdi --resize 10000
NB: For compatibility with earlier versions of VirtualBox, the "modifyvdi" and "modifyhd" commands are also supported and mapped internally to the "modifymedium" command. see Chapter 8. VBoxManage
Increase the partition size
Just by increasing the size of the hard drive will not increase the size of the Partitions so now we have to make the partition(s) bigger
Your sda2 partition will not have 10GB of free space.
Notes
Notes on partitions, their layouts and the process of making more space available to LEDE in a virtual machine.
Quick Setup
LEDE will now boot but we will not be able to access it because the IP address is wrong. To fix that:
Because we used the stable release when LEDE is booted up you can access LuCI via you browser by using the address http://192.168.56.2/ .This means you can do a lot of editing in the GUI rather than the command line. If you used a snapshot you will need follow the Full Setup shown below and install LuCI manually.
Full Setup
There are many more settings that 'might' need to be done but I have not got that far yet.
You are all done now, enjoy!!!
These are some other things that do not fit into the guide above but might be useful for some people.
I do not know how to do this. I am guessing you just update the root/system/sda1 partition with either of these packages as appropriate:
If you get I/O errors when using the uci command it is probably caused by lack of free space on the file system. Instructions below. Using VI will not fix these errors but will let you change the IP address in /etc/config/network so you can access LuCI for easier diagnosis.
Just incase you cannot make any changes with the uci commands then here is a crash course on VI editor
Notes
You really should disconnect a VDI image from Virtualbox via the 'Virtual Media Manger' before moving the VDI file but if you dont here is the quick way of fixing that issue.
Notes
Updated to [OpenWrt Wiki] OpenWrt 21.02.1 - Service Release - 25 October 2021
These instructions are for aimed at users of Windows but a lot of the information will work for other OS users.
I wrote these instructions just to clear few things up so next time I flashed a BT Home Hub 5 Model A (HH5A) router, it would be easier. The instructions done by other people are not necessarily faulty but not as clear as I needed at points and this mini guide will address those. It must be said I am also a bit of a newbie at electronics so not everything is obvious.
These instructions are complementary to the guides and information that has already been done by the community and in particular thanks goes out to:
My guide covers all aspects of this process:
If you do not open the case carefully you will break the 'fixing tabs' inside. I broke them on my first go and then repaired them with a soldering iron. Look at these instructions in order on how to open the case.
Before you start soldering read this article:
Simple no soldering flashing jig made from a cat5e keystone jack - openwrt.ebilan.co.uk
It is perfect for those who cannot solder. You will need to buy a RJ45 Network Keystone from eBay.
You can use your own method for soldering the connections as long as you have access to the required connections on the circuit board and can attach them to a USB to TTL RS232 Converter.
People have done this many different ways but I am going to replicate the arrangement on the OpenWrt BT HomeHub 5.0 Type A as this is the page most people will land and the method is quite clean.
You do not have to use the ground points that I have used based on the OpenWrt BT HomeHub 5.0 Type A page.
This method described on this page mounts a 5 pin header block designed for reuse.
Before soldering, you need to know what you are soldering and why.
The images and instructions could be a little clearer about what is actually soldered to where, so I will just clear that up now.
I have taken the image off the OpenWrt HH5A page that shows the wires connected and then labelled the connections with an accompanying table below showing the connections. These are now labelled in a logical order and are easier to follow but do not have the same numbering as the OpenWrt HH5A page.
Image from the OpenWrt HH5A page
Pin No. | USB Serial to TTL Adapter | Wire Colour | Home Hub Connection Point |
1 | n/a | Blue | boot_sel2 / R45 Pad |
2 | n/a | n/a | GND / Use the USB socket ground/case pin |
3 | TX | Blue | RX / R78 Pad |
4 | RX | Purple | TX / R77 Pad |
5 | GND | n/a | GND / Use the ground plane connection of the capacitor |
This is a close up of the pads
Image from the OpenWrt HH5A page
Fitting the 5 pin header and soldering the wires to the pads
These are my newbie notes
Soldering instructions
Example of neat soldering
Follow the instructions from 1-OpenWrt-LEDE Installation Guide for HH5A.pdf (ebilan) and use this as a companion guide.
Download Firmware / Install Files for the HH5A
You should of downloaded these from the prerequisites section.
Install the required software
Connect the adapter
Configure Putty
Access the router firmware via the console
With putty running and the adapter connected:
Transfer ‘HH5A LEDE/OpenWrt install image’ to the router
Now move on to the 1-OpenWrt-LEDE Installation Guide for HH5A.pdf (ebilan) as the rest of the instructions should be the same as the linux OS.
Backup BT Firmware (ebilan 3.0)
Before doing anything else you need to back your routers original firmware.
When you remove a pendrive from windows you should eject it properly so the volume is not marked as dirty
ls /tmp/mounts
ls /tmp/mounts/USB-A1
nanddump -f /tmp/mounts/USB-A1/hh5a.nanddump /dev/mtd4
umount /tmp/mounts/USB-A1
Replace the stock BT firmware (ebilan 4.0)
prepare
sysupgrade /tmp/mounts/USB-A1/lede-lantiq-xrx200-BTHOMEHUBV5A-squashfs-sysupgrade.bin
Backup settings - (ebilan 4.3)
Always backup your current OpenWrt configuration before making any significant changes.
We have now installed OpenWrt successfully installed on our HH5A. You should now follow my instructions but I still use references to the 1-OpenWrt-LEDE Installation Guide for HH5A.pdf (ebilan) tutorial.
The following are my instructions on how to configure OpenWrt to give the same functionality (and more) of the orginal HH5A.
(System-->Administration-->Router Password)
Notes
This is optional and probably does not need changing for most peoples setup.
(System --> Administration --> SSH Access --> Dropbear Instance --> Interface)
(Network --> Interfaces --> Wireless)
Only change things if they are noted below, else just leave as is. Some items are left in for reference if you are wondering.
Set the WiFi SSID and encryption with a suitable password
Notes
(Network-->Interfaces-->WAN-->Edit)
(Network-->Interfaces-->DSL)
(Network-->Interfaces-->ATM Bridge)
Now Reboot Router (System-->Reboot)
OpenDNS / Quad9 / Custom DNS servers
This still sends 192.168.1.1 to the clients but sets the DNS servers used by the router to OpenDNS
Notes
Notes
Notes
I currently do not have any specific configurations for the firewall because it has all been done.
Notes
You are able to configure the router's 3 compound LEDs to provide feedback from the router's various functions with a selection of colours which can also be controlled independently.
There are some really nice features you can add such as the heartbeat effect where you can translate the CPU load in to a heartbeat pulse via the select LED. I use the WiFi LED configured as red.
Colours available
Notes
Links
This section contains various configuration for your HH5A LEDs.
Default OpenWrt Configuration
This is the default configuration for the LEDs when you first install OpenWrt.
config led 'led_wifi' option name 'wifi' option sysfs 'blue:wireless' option trigger 'phy0tpt' config led 'led_dsl' option name 'dsl' option sysfs 'blue:broadband' option trigger 'netdev' option mode 'link tx rx' option dev 'dsl0' config led 'led_dimmed' option name 'dimmed' option sysfs 'dimmed' option default '0'
Configure LEDs to be like the HH5A
This is not exactly the same as the default BT HH5A LED configuration because the LED configuration in OpenWrt lacks the features I need to program this.
This configuration will do the following:
In LuCi
This is the code the rules above create in the /etc/config/system file.
config led 'led_wifi' option name 'wifi' option sysfs 'blue:wireless' option trigger 'none' config led 'led_dsl' option name 'dsl' option sysfs 'blue:broadband' option trigger 'netdev' option dev 'dsl0' list mode 'link' config led 'led_dimmed' option name 'dimmed' option sysfs 'dimmed' option trigger 'default-on' option default '1'
Disable Power LED / Other LED
It is possible to disable the Power LED (or other LED) by adding a new rule via LuCI or directly in the /etc/config/system file. The Power LED is turned on by the bootloader and this is why you need to add an extra rule whereas other LEDs you could just delete the rule that turns them on.
In LuCi
Or you can add the following code directly into the /etc/config/system file.
config led option name 'power' option sysfs 'blue:power' option trigger 'none'
This is the default LED behaviour of an unmodified HH5A and I can use this to program up the LED behaviour in OpenWrt to match this default behaviour when the required functionality is added in a future version of OpenWrt.
Booting a configured router with DSL plugged in
Router bootloader
Router has booted
NB: occasionally at 1:15 the orange light goes solid while the internet led flashes about 4 times before resuming flashing orange.
Remove DSL wire from a connected and configured router
Plug in DSL wire to a configured router
Hold the WPS Button
(System-->Software)
Your Router must be on the internet to be able to install software
These extra features do not come pre-installed in OpenWrt so need to be installed. The GUI (web interface) is called LuCI and all of the GUI add-ons are prefixed with ‘luci’ so you can search for just GUI add-ons by using the search term 'luci-'. I have found that if I install a ‘LUCI’ add-on then the other dependencies such as the actual service it will controls gets installed as well. This is why using LuCI is much better for most people than using the command line.
The plugins I have listed below are the main ones to get your router doing the original HH5A features and the little extras to make life easier.
There is currently no place online you can browse the software repository. The best place for descriptions is to type something in to the search box on the software page of your router and look at the packages you want to install and you will see a brief description of them but only on the 'Available Packages' tab.
Please bear in mind this is my setup to get a good baseline as close to the HH5A as possible. All those add-ons that have (not used) means I have installed them to make sure they work but have uninstalled them because I did not want the features they offered. Some people might want those features so I have left the install notes here for reference.
The optional add-ons should only be installed if you want those features. All the rest of the add-ons should be installed unless you absolutely do not need those features.
OpenWrt will run with none of these add-ons installed.
Add-on Notes
You need to use this to edit config files with windows using WinSCP or FlashFXP which is easier than the command line but this requires a little configuration. You can use SSH and edit via the command line using the VI editor.
Install Notes
[15:11:23] [R] Connection failed (Unable to access SFTP sub-system, operation failed.) [15:11:23] [R] Delaying for 10 seconds before reconnect attempt #1
FlashFXP/WinSCP
Notes
cat /etc/config/packages.list
UPnP is not installed by default.
Once installed UPnP will need to be turned on.
WPS doesn't work out of the box on OpenWrt, you need to:
Notes
This is cannot be used use WPS as they use the same button, otherwise you can use this to configure the WPS button for something else such as turning the WIFI on or off.
Notes
You only need this if you want to play around with the web server settings. Most people will not need this.
Notes
This is a must nowadays, and there are 2 ways of doing it.
uci set uhttpd.main.redirect_https=1 # 1 to enable redirect, 0 to disable redirect uci commit uhttpd service uhttpd reload
Secure Connection Failed
If you get the following message after you have forced HTTPS then is it most likely a certificate mismatch error and all you have to do is closes and restart your browser.
Notes
This is now enabled by default by default OpenWrt 21.02 I will leave this section here as a reference.
This installs https for LuCi, the required SSL libraries and disables http:// for LuCI,
Notes
SSL is not installed by default OpenWrt 21.02 so you do not need to install SSL or CA-Bundles. I will leave this section here as a reference.
There seems to be a few SSL packages but most people seem to use one which is the package that is used by LuCI for https/SSL (see below).
Basic Open SSL
This will install the minimum to use SSL
This installs all root certificates as one bundle file and seems to be updated on a regular basis to keep upto date with certificate authority changes. Root certificates are required to validate HTTPS certificates.
ca-bundle vs ca-certificates
I do not know why there is ca-bundle and ca-certificates but I believe that ca-bundle is all of the root certificates in one file where as ca-certificates the root certificates are all separate and that some programs require them to be separate. Which ones these are is beyond me and unless otherwise told I will use ca-bundle.
Control the ACME LetsEncrypt certificate interface. For you that dont know, LetsEncrypt gives out free SSL/TLS certificates.
Notes
LuCI support for Adblock
Notes
# Adblock - Block list update
0 06 * * * /etc/init.d/adblock reload
This updates the block list every day @ 06:00LuCI Support for Dynamic DNS Client (ddns-scripts). The HH5A has this, but is optional to install.
Configuring no-ip.com as a custom DDNS provider
For some reason no-ip.com is not in the list of DDNS providers and by the looks of it people have been using a custom script for no-ip.com. I dont know wether that is still the prefered method by most people.
no-ip.com now offer the standard http/https API method of updating the DNS records with them, so that is my prefered method of updating no-ip.com DNS records.
In (Services-->Dynamic DNS-->myddns_ipv4) configure these settings
These settings work fine and are using normal http.
You need to install SSL to use HTTPS
To use SSL you needs to install the basic SSL package or install https for LuCI will also install the basic SSL package and make the web interface use https at the same time.
If you try and use https for DDNS without installing a suitable SSL package you will get the following error and The DDNS service will also fail to start:
223214 WARN : uclient-fetch: no HTTPS support! Additional install one of ustream-ssl packages - TERMINATE
223214 WARN : PID '4597' exit WITH ERROR '1' at 2017-11-23 22:32
The resolution is simple, Install SSL functionality by following the instructions in the sections below.
Configure DDNS to use https
Making DDNS use https is really simple
Notes
This section is not complete. check out the links to get things working.
Ebilan now has a document on how to do this in his DropBox Repo
LuCI Support for OpenVPN
Notes
Links
ClamAV is an anti-virus package you can run on the router independant of the clients but it is CPU intensive. This is better suited for higher spec setups such as virtual machines.
Notes
Out of the box, OpenWRT can show you real-time statistics, however it will not store the data for historical view. Install luci-app-statistics to have a nice historical data graphs for router, eg: ping, interfaces bandwidth utilization, cpu load, ram, disk, uptime, etc…
This needs its own section because there are several ways of encrpting your DNS request and also there is DNSSEC.
See the different methods below and pick whichs ones are right for you, but my recommendation is:
- DNS Hijacking (via the Firewall)
- Requires dnsmasq-full to filter by IPSets.
- dnsmasq-full
- Supports DNSSEC
- Easy to use with Stubby for DoT
- Closet to dnsmasq in terms of config and current LuCi setup
- I dont need a full authoriative recursive DNS server (you need Unbound for this)
- You need dnsmasq-full to do DNSSEC validation locally and you only need to do this if your upstream DNS provider does not do it for you.
- DNS Hijacking needs dnsmasq-full to filter by IPSets.
- DoT (dnsmasq and Stubby)
- IT manages can still control traffic.
- Doesn't require a full HTTPS stack like DoH
- more compatible with devices
- DoT runs on a different port so is easier for traffic management
- Less resources needed
- Your local ca-bundles must be upto date (there might an override but this would defeat the object of DoT)
- dnsmasq supports IPv6
- Quad9
- It Supports DNSCrypt, DoH, DoT, DNSSEC
- I think it validates DNSSEC on it's own server so i dont need to install dnsmasq-full to do this locally.
- Its purpose is to send NXDOMAIN responses for domains that are flagged as malware/dirty.
- DNSSEC (dnsmasq)
- This validated cryptographocaly the domain you are talking it legitimate and not spoofed.
- The DNSSEC validation is done at Quad9 servers
- I dont believe I dnsmasq-full for this to work as I was getting verification just using dnsmasq
- With just dnsmasq I went to intentionally misconfigured domain and Quad9 blocked me as expected.
This script allows OpenWrt to intercept all DNS traffic from your local network and send it to your preferred DNS provider. This is useful nowadays because of all of the encrypted DNS traffic from various apps and devices on your network.
Standard DNS and DoT are easy to identify becasue of the port they run on, however for DoH you need to match the domain the packet is being sent to from a known list DoH which is updated regulary via the hotplug.d, you can see in the code where the list is if you want to have a look.
To install DNS Hijacking run the following code blocks from the official documentation [OpenWrt Wiki] DNS hijacking via a SSH command line
# Upgrade to dnsmasq full opkg update opkg remove dnsmasq opkg install dnsmasq-full
Notes
Tutorials
Using this feature and OpenDNS (or other DNS provider) adds extra security to your network and prevents rogue uncontrolled DNS requests.
This option adds a rule into the OpenWrt firewall so all DNS requests are forced to the router and if you have set up OpenDNS as a custom DNS server then all DNS requests will be sent to OpenDNS via the router.
Firewall rules have now been added to accomplish this however the firewall rules are removed when the Adblock service is disabled or you uninstall the adblock package.
From looking at this, these rules will only work for DoT and not DoH traffic.
Keep firewall rules for DNS requests but disable the Adblock service
When you disble the adblock service under (Adblock-->Settings-->General Settings-->Enabled) the firewall which force DNS routing are removed. Sometimes you might not want the Adblock service but really want the DNS funnelling rules. So this is how to keep the rules and have the adblock service disabled. If you really want you can manually add these rules to the firewall but who wants to do that.
Now the Firewall rules are still in place and the adblock service is not running. It will also not restart the service when you reboot your router.
config redirect 'adblock_lan53' option name 'Adblock DNS (lan, 53)' option src 'lan' option proto 'tcp udp' option src_dport '53' option dest_port '53' option target 'DNAT' config redirect 'adblock_lan853' option name 'Adblock DNS (lan, 853)' option src 'lan' option proto 'tcp udp' option src_dport '853' option dest_port '853' option target 'DNAT' config redirect 'adblock_lan5353' option name 'Adblock DNS (lan, 5353)' option src 'lan' option proto 'tcp udp' option src_dport '5353' option dest_port '5353' option target 'DNAT'
This is very easy to set up and the 2 options I recommend are (both have the same end result:
If using a DoT/Stubby setup: When you do a router upgrade you will temporarily change your WAN/WAN6 DNS settings to 9.9.9.9/2620:fe::fe while you install the required packages because without this change your router will not be able to talk to the internet for this process.
Sat Nov 27 17:24:00 2021 daemon.err stubby[3738]: Could not schedule query: None of the configured upstreams could be used to send queries on the specified transports
WAN Up --> Stubby Up --> No internet --> Errors WAN Up --> Pause 4 seconds --> Stubby Up --> Internet --> No Errors
option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20' option tls_ciphersuites 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256'Please note that the following line is for TLS1.2 only and should be left commented out aws it is not needed.
# option tls_cipher_list 'EECDH+AESGCM:EECDH+CHACHA20'
OpentWrt comes with the small version of dnsmasq which is fine for most basic operations but DNSSec requires the full package to be installed.
It should be possible to run DNSSec and DNSCrypt if the target DNS server supports both of these technologies.
You probably will receive the follow error:
Collected errors: * resolve_conffiles: Existing conffile /etc/config/dhcp is different from the conffile in the new package. The new conffile will be placed at /etc/config/dhcp-opkg.
Compare the config files
You should note there might be more that one service using the dhcp config file.
Enable DNSSec
DNSSec is not enabled by default so will need to be turned on.
dnscrypt-proxy is an application that acts as a local DNS stub resolver using DNSCrypt. It encrypts your DNS traffic improving security and privacy. dnscrypt-proxy is the client-side version of dnscrypt-wrapper. Follow DNSCrypt with Dnsmasq and dnscrypt-proxy to properly setup DNSCrypt via dnscrypt-proxy on your router.
https://dns.quad9.net:5053/dns-query?name=quad9.net https://9.9.9.9:5053/dns-query?name=quad9.net
ssh root@192.168.1.1 tcpdump -i br-lan -U -s0 -w - 'not port 22' | "C:\Program Files\Wireshark\Wireshark.exe" -k -i -
You can find a full list of devics to monitor by going to (Network --> Interfaces --> Devices) or (Status --> Realtime Graphs --> Traffic)
ssh root@192.168.1.1 tcpdump -i dsl0.101 -U -s0 -w - 'not port 22' | "C:\Program Files\Wireshark\Wireshark.exe" -k -i -
In this section we just make changes that are appropriate here.
This error appears in your system error log. It will not cause any real issues but explanantions and solutions are below.
Mon Nov 29 15:56:12 2021 daemon.err odhcp6c[1363]: Failed to send SOLICIT message to ff02::1:2 (Permission denied) Mon Nov 29 15:56:13 2021 daemon.err odhcp6c[1363]: Failed to send RS (Permission denied)
Cause
Solutions
Pick one of the solutions below.
Links
This is only useful if you have mulltiple routers running AP (Acccess Points) on the same SSID.
Notes
Method 1 - Easy
This is based on a post from @Mushoz on the OpenWrt forum here Fast Roaming 802.11r - Multiple SSIDs = different mobility domains? | OpenWrt Forum where he says the Mobility Domain is created automatically by hashing the SSID.
Method 2 - Manual (Van Tech Corner)
This is a very useful video from Van Tech Corner OpenWRT - Configure 802.11r Fast Transition - Fast Roaming Wifi - YouTube
After configuring the router you will want to backup your settings
Notes
Do not upgrade over WIFI and read How to update OpenWrt (ebilan 4.3)
It is ok just to use the basic LuCi upgrade procedure for minor versions, but you will probably find with major verion updates there are syntax differences within the config files and these need to be manually resolved. Always use the new config files as the base and move your settings into them.
When merging move the settings you understand and for those that you are not sure about go and find them in the LuCi GUI and see what they match up to.
- If using a DoT/Stubby setup: When you do a router upgrade you will temporarily change your WAN/WAN6 DNS settings to 9.9.9.9/2620:fe::fe while you install the required packages because without this change your router will not be able to talk to the internet for this process.
- Custom scripts might need to be re-installed eg: IP set extras and Hotplug extras required for DNS Hijacking (via the Firewall) (i am not 100% sure if this is the case for these scripts).
It should be noted that this method (on it's own) will require you to re-install all of the 3rd party packages manually for the new firware to be the same.
Manually removed/installed packages are not preserved by default so we must make note of them before upgrading.
Not Added To Archive
- Removed packages are not recognised in the installed_packages.txt currently and will still be present after restoration.
- Service startup status are not maintained either.
- An example is that this will affect people who disable the dsl_control service to prevent the restarting bug.
- Automatic statirng of a script is based on the presence of a symbolic link to it in the folder /etc/rc.d
- The startup scripts are stored in /etc/ini.d
- It would be nice if this was preserved in the backup archives.
- [OpenWrt Wiki] Init Scripts
These are based on official instructions [OpenWrt Wiki] Backup and restore - Preserving packages and the Luiz Angelo Daros de Luca method shown below.
installed_packages.txt issue in recent OpenWrt21.02.1 release
There has been a change and for some reason I cannot write to the /etc/backup/ folder, however the installed_packages.txt if enabled in the config backup will still be present in the backup. It might be this folder is now getting purged automatically. I have made some adjusments to the code below but have left the old stuff there just incase this is just a bug in 21.02.1 - It should be noted I can still place files in this folder with SFTP and that if i place installed_packages.txt this does not get overwritten but the backup folder in the archive now has 2 installed_packages.txt indicating the file is created elsewhere. This might be an issue with the /overlay and /rom partitions.OpenWrt Bug Report: FS#4048 : sysupgrade with "-k"
For the instructions to work below you must
- make sure the installed_packages.txt is included in the backup configuration.
- output the file to the config directory and dont delete it sysupgrade -k -u -b /etc/config/deleteme.tar.gz
- FTP or otherwise transfer the backup archive from your router
- The installed_packages.txt will be correctly present at /etc/backup/installed_packages.txt
- The normal backup archive will NOT have the installed_packages.txt present.
sysupgrade -k -u -b /etc/backup/deleteme.tar.gz # rm /etc/backup/deleteme.tar.gz
/etc/backup/installed_packages.txt
opkg update grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg install rm /etc/backup/installed_packages.txt reboot
Collected errors: * check_conflicts_for: The following packages conflict with wpad-wolfssl: * check_conflicts_for: wpad-basic-wolfssl * * opkg_install_cmd: Cannot install package wpad-wolfssl. xargs: opkg: exited with status 255; aborting root@officerouter:~# rm /etc/backup/installed_packages.txt root@officerouter:~#
adblock adblock-opkg
These will need to be compared with a merging program and you will need to make manual changes where needed. Try and keep the layout of the new config file
opkg list-installed | cut -f 1 -d ' ' > /etc/config/packages.listThis will create a file called packages.list that will survive a flash when you keep the settings.
cat /etc/config/packages.list | opkg install
This will now install the missing 3rd party packages.
Notes
This is a another method that I have come across and is developed by the person responsible for sysupgrade (I think)
sysupgrade -o -k -u openwrt-new-version.img <auto reboot> opkg update grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg install rm /etc/backup/installed_packages.txt reboot
Notes
When you have anoter router OpenWrt router on which you did not create the config backup on but want that same setup on there are a few things you need to do. I will use my setups as an example which might only need a few tweaks for yours, but you will get the idea.
grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg install
sysupgrade --help
With '-u', for a file /aaa/bbb/ccc enlisted for backup, it will only get into backup if /rom/aaa/bbb/ccc does not exist or /aaa/bbb/ccc is different from /rom/aaa/bbb/ccc. It also works with '-c', but only effective for files touched but not modified.
Upgrading all packages without updating the firmware of the router is something you possibly want, so here it is:
opkg update opkg list-upgradable | cut -f 1 -d ' ' | xargs -r opkg upgrade
Stuff that was not covered above will be here.
What Happens
Notes
When you uninstall a piece of software, this will not remove the dependencies automatically (OpenWrt should add a dependencies register to fix this). If you want to try out a new add-on, do the following so if the add-on installs a load of stuff you do not want you can remove the dependencies and revert back to your old settings.
Installing
Removing
Failsafe mode is where you can access OpenWrt Console/Linux Kerel via SSH or a serial connection and is used for those times OpenWrt will not boot up.
To access the Failsafe mode by SSH
Notes
Config file conflicts can happen at various times but in this instance it was when I had done the following
I then received the following error:
Collected errors: * resolve_conffiles: Existing conffile /etc/config/ddns is different from the conffile in the new package. The new conffile will be placed at /etc/config/ddns-opkg.
What this error means is that when i downloaded luci-app-ddns, OpenWrt discovered I already had a config file called ddns so it just renamed the new/default config file that came with the package to ddns-opkg so my original config file that had been restored with my backup was unaffected and I still had the opportunity to examine the new config file to see if there were any changes.
You can delete the file ddns-opkg as it is not used. You might want to just look in it to see if there any changes you need to know about.
Notes
I will briefly outline the security settings I have added to my OpenWrt HH5A setup. This might change over time.
Notes
I have not verified the answers to these so any feedback is welcome.
These settings here are useful ones I have come across but do not form part of the intial configuration of OpenWrt for the HH5A.
Wireless Isolation
This is not available for configuration in LuCI and the correct format seems to be option isolate '1'
Prevent Windows adding a new network every time the OpenWRT router is rebooted
General
Flashing Guides / Tutorials
Documentation / Configuration
Tech Specs
Websites of note
Forums
BT HomeHub stuck in CFG04 (UART) mode after installation
Logging
The UCI system
Questions
These instructions do not cover the basic usage of the scotle/BGA Rework machine and how to program it etc.. but shows you have to make the perfect profile that you can use. Profiles are very specific to your machine and environment but there is a basic method that can be used on how to make these profiles that I have worked out and I will now show you.
My scotle is a 3 zone BGA rework machine however these instructions will work for a normal 2 zone machine. All you have to do is skip the lower HR zone bit. Also if you have an upper HR machine these instructions will work the same.
So the 3 temperatures we will need to figure out are
Splifire mods recommending flatlining your machine, which basically is figuring out what your preheat ranges and temperature settings should be (at the point your top heater is initiated)
Other settings
So firstly we will prep out our machine
Notes for testing
NB: johnnyx method usesthe scotle main probe on the top of the motherboard for the temperature (of 180c) and sets the upper IR to 0c long dwell, he also sets the lower HR to match the lower IR and then gets the temperature needed. This puts at risk the board as you do not know what temperature the lower componenets are exposed to. This method is probably ok for naked boards like the xbox 360.
Instructions
You could use the profiles for the Upper IR/HR and Lower HR and set them to 0c and a large dwell time so you could use the inbuilt temperature probe, but the reason I have not is that the Lower HR on mine will always kick out air and if it is not heated it is cold which could affect my profiling. By getting just the IR preheated temperatures first I can find out what is safe.
NB - sort
Now
A table showing when the lower board Temperature Reached was reached (mins) and what the Lower IR presheater were set at.
Room: c |
Lower IR Temp |
180 |
185 |
190 |
195 |
200 |
210 |
220 |
225 |
Lower Board Temperature |
|||||||||
140 |
|||||||||
145 |
|||||||||
150 |
|||||||||
155 |
|||||||||
160 |
|||||||||
165 |
|||||||||
170 |
|||||||||
175 |
|||||||||
180 |
|||||||||
185 |
|||||||||
190 |
|||||||||
195 |
|||||||||
200 |
|||||||||
205 |
|||||||||
210 |
|||||||||
215 |
NB: make a note of the room temperature and lower board temp before you start.
My actual results
Room: 20c |
Lower IR Temp |
180 |
185 |
190 |
195 |
200 |
210 |
220 |
220 2nd |
225 |
225 |
Lower Board Temperature |
|||||||||||
140 |
3:57 |
3:24 |
3:45 |
3:50 |
2:32 |
3:38 |
2:88 |
2:24 |
2:20 |
3:27 |
|
145 |
4:08 |
3:45 |
3:52 |
4:05 |
3:48 |
3:46 |
2:35 |
2:27 |
2:24 |
3:38 |
|
150 |
5:08 |
3:55 |
5:04 |
4:59 |
3:54 |
3:50 |
2:42 |
2:45 |
2:27 |
3:48 |
|
155 |
6:34 |
6:12 |
6:13 |
6:16 |
4:08 |
4:00 |
3:48 |
3:48 |
2:37 |
4:47 |
|
160 |
7:50 |
6:23 |
7:39 |
6:22 |
5:11 |
5:11 |
5:04 |
3:53 |
3:53 |
4:55 |
|
165 |
11:34 |
7:39 |
8:53 |
8:44 |
6:28 |
5:22 |
5:24 |
5:17 |
3:59 |
5:08 |
|
170 |
13:15 |
8:51 |
11:30 |
9:04 |
7:37 |
6:56 |
6:27 |
5:20 |
5:09 |
5:16 |
|
175 |
18:14 |
10:36 |
13:51 |
11:22 |
9:09 |
8:02 |
6:30 |
5:42 |
5:22 |
5:21 |
|
180 |
- |
15:00 |
14:00 |
13:08 |
10:31 |
10:58 |
6:38 |
6:56 |
5:42 |
7:47 |
|
185 |
- |
- |
- |
17:14 |
15:51 |
13:32 |
6:42 |
7:07 |
9:19 |
9:56 |
|
190 |
- |
- |
- |
- |
19:11 |
16:21 |
11:24 |
10:19 |
9:34 |
11:15 |
|
195 |
- |
- |
- |
- |
- |
- |
12:28 |
12:18 |
12:48 |
12:25 |
|
200 |
- |
- |
- |
- |
- |
- |
15:17 |
15:48 |
17:44 |
14:09 |
|
205 |
- |
- |
- |
- |
- |
- |
- |
17:40 |
18:55 |
15.28 |
|
210 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
18:34 |
|
215 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Notes -
Choose you lower IR temperature
You results are now in. We are looking for a Lower board temperature of 170c/180c in about 7 – 8 minutes. Now this is a guideline so If yours are slightly out don’t worry too much. If you are using a 3 zone machine you can get a away with 170c because your 3 zone (lower HR) will more than compensate for this.
When looking at the table you can see that all of the runs have the same sort of profile, they heat up rapidly and the slow right down when they get to about 75% max temp of the run, they then eventually hit the max temp and stay there.
My results above are the times when the temperature on my TM-902C reached that value. This is most likely at the top of the range of the actual temperature. I on avergage so a range on about +-10c so I would know off 5c off the tempratures reached and then use those. This might not be the case for the temperature senor you use especially if the result on screen is steady.
This means I will use 210c as it reaches 170c @ 7:37 mins. It should be noted that the max temperature for this run is 210c which is 10 degrees below the dangerous 200c.
On a warm day I might use 200c. It should also be noted I am in the north of England and it is cold,and I am using the scolte unmodified (i.e. the spitfire lower IR temp mod)
Before I start this section I need to tell you what a 3rd zone or lower HR heater is for. If you don’t have one you can skip this section
In our tests in the above section (Lower IR) we did not have the lower HR on and if we had tested the top board temperature above the HR unit, i.e. under the target chip we would have found it to be a lot lower than the rest of the board. (Literally the cold HR unit was in the way and there are no lower IR plates delivering heat to that part of the board, or definitely a greatly reduced amount.)
With this section we will use our choosen lower IR plates temp (200c) and try to findout what lower HR temperature setting will deliver 170/180c to the top of the board under the chip at the 7 – 8 minutes mark.
Instuctions
The easyway is just to set your lower HR to the same temp as lower IR plates with a ramp rate of 1
Run these instructions for each Lower HR temperature
Notes
A table showing when the upper board Temperature Reached was reached @ (mins) and what the Lower HR was set at. I have also added actual lower board temperature
Room: c |
Lower HR Temp |
180 |
185 |
190 |
195 |
200 |
210 | 220 | 225 |
Upper Board Temperature |
|||||||||
140 |
|||||||||
145 |
|||||||||
150 |
|||||||||
155 |
|||||||||
160 |
|||||||||
165 |
|||||||||
170 |
|||||||||
175 |
|||||||||
180 |
|||||||||
185 |
|||||||||
190 |
|||||||||
195 |
My Results
Room: c |
Lower HR Temp |
180 |
185 |
190 |
195 |
200 |
210 | 220 | 225 |
Upper Board Temperature |
|||||||||
140 |
3:46 | ||||||||
145 |
4:06 | ||||||||
150 |
4:29 | ||||||||
155 |
5:02 | ||||||||
160 |
5:45 | ||||||||
165 |
9:27 | ||||||||
170 |
- | ||||||||
175 |
- | ||||||||
180 |
- | ||||||||
185 |
- | ||||||||
190 |
- | ||||||||
195 |
- |
Some notes - sort
Next phase - Build profile preheat segment
This will include
so at 5:45 mins the top board temperature is 160 and bottom board temperature is 160c(+/-10c) so the settings for me should be as follows:
Now build your profile
I have designed a project using smarty and I have decided that the easiest way to add a transaltion system was to use gettext() because it was widely supported. I shortly discovered there were many issues with it which I have resolved bar one, scanning smarty .tpl files with Poedit. I am not going to do all my translations manually!!!
I managed to get quite far using poedit and messing with the various parsers but they were not 100% for me.
The goto plugin for smarty to add gettext support is smarty-gettext , a plugin that allows you to put text you want to translate inbetween some custom tags and then these will be translated into gettext() statements.
{t}....{/t}
Now Poedit will not find these tags, nor can you config custom scans for it in the software. You can however use external extrators to do this.
smarty-gettext has a command line parser that will scan your .tpl files and return correctly formatted .po and .mo files but this means you have to scan from the command line with this script, then you have to use Poedit to scan your PHP files which could get quite messy and then somehow merge the 2. So to that end I have manged to get the command line parser to function as a Poedit extractor. I will also go through the different parts of the process so you can perhaps build your own parser or utilise one that is already there. I have also found a few other Poedit parsers that might be of use and i will also list them later.
These instructions were written with gettext() in mind but because of caching issues with gettext() I decided to use motranslate. The instructions are exactly the same for both technologies except you need to add some Additional keywords for motranslate.
My advise is to follow these instructions carefully and then once you have the process working it is at that point you should alter it to your needs. These instructions are also for Windows and Xampp.
I will be using my file locations so everything matches up. I will also assume
When specifying a directory the script will only search within .tpl files and I need it to search with some .js files I have in my project. So edit the file and change:
// extensions of smarty files, used when going through a directory $extensions = array('tpl');
to
// extensions of smarty files, used when going through a directory $extensions = array('tpl', 'js');
- I added the 2 folders to the windows PATH so the files within can be found easily. You can probably get all of this working without adding stuff to the PATH but I would not reommend it. php.exe, msgcat.exe and msgmerge.exe all need to be found for this to work.
- You could probably get away with just adding the D:\websites\php tot he PATH but I found it neater to have these other files in their own folder.
- I choose the static versions for the gettext() package so I did not have to worry about if the .dll files were registered or could be found
- xammp does not need to be running
- make sure you do not have other version of gettext in the path otherwise the software can get confused
All the files and settings are inplace we now need to configure Poedit. Make sure you download the older v1.8.13 version because you can still see how all of the parsers are configured.
On the orginal Poedit (v1.8) you were able to select which parsers were enabled. These were all configured the same except for the language type and what files they scanned. In v2.0 this has been removed. Below is the PHP Extractor setupfrom v1.8.
I have been using Poedit v2 with success for QWcrm.
Instructions
Search all folders supplied by Poedit (recommended) php "D:\websites\php\tsmarty2c.php" -o %o %F Only searches in the folder 'themes' php "D:\websites\php\tsmarty2c.php" -o %o themes
D:\websites\htdocs\develop\qwcrm
cache\ nbproject\ libraries\ logs\ media\ themes\default\js\dhtmlcombo\ themes\default\js\tinymce\ themes\default\js\jscal2\jscal2.js themes\default\js\jscal2\unicode-letter.js themes\default\js\jscal2\css\
_gettext - This is for the function _gettext() __ - This is for the function __()
NB:
I will just explain a little here about this extraction process. All of the other Extractors are using xgettext() to scan files and return a correctly formatted .po file. xgettext() is dated and will not recognise a lot of languages and you can not add custom scans in to it.
Poedit extractor switches explained (This is useful so you can workout how to build you own parser.)
- -o - This is just a standard switch that is pass to the extractor. It is not specific to Poedit. However the xgettext() uses this to denote the output file and so does tsmarty2c.php
- %o - this is a placeholder for Poedit to swap out with the tempory .pot file location where changes are merged to.
- %k - this placeholder is to be able to pass custom function names to your script (or xgettext) to scan within for strings i.e. instead of gettext("translate me") you could scan for chicken("translate me") or football("translate me"). It is not mandatory to have this.
- %f - this is placeholder for the file list. I am not sure of the format but it is in a format that ngettext() will accept. All files are passed in 1 large list here. I can't work out if this is type, but to pass the list you need to use %F.
- --from-code=%c - this is always added on to the end of the command line and is to specify what charset the files houls be open as. I do not need this so have removed it. I thing it is mainly for xgettext. My scripts have been running with it attached though.
- NB: the instructions for Poedit for the extractors does not make sense. There is information left out.
So what happens with an extractor when you hit 'update from sources'
- poedit scans the project's folders (as per your rules) for allowed files and builds a list
- one of the following happens (not sure which)
- The files are passed as a single command line to an extractor that matches the file extensions (possible goes to multiple extractors if an extension is registered in more than 1 extractor)
- Each file is passed as a single command line to an extractor that matches the file extension (possible goes to multiple extractors if an extension is registered in more than 1 extractor)
- the extractor then parses these files and then merges the strings it finds to a temporary pot.file (using msgmerge.exe)
- the next extractor is run and those files are merged into the same temporary .pot file(using msgmerge.exe)
- once finished Poedit loads this temporary .pot file in to memory and you are returned to the main screen
- your changes have not been saved yet. For this you actually need to hit save to apply the changes to you .po file.
- Poedit will now build the .po and .mo files
Comodo Sandbox which is part of the comodo Internet Security (CIS) if running will cause the extraction process to fail because it blocks the PHP script. You need to disable the Comodo Sandbox before running the extraction. This might also be the case for other sandboxes and Firewalls.
So now run Poedit and extract the translations as outlined above by hitting the Update from sources menu item of click the Update button.
gettext() is a translation system written by GNU people and is present on many systems natively. This makes it a good standard to use. Gettext does have some issues especially on PHP and I will outline what I have found here with possible solutions
I now use motranslator which is based on the same technology as gettext because of the following:
- gettext translation file (.mo) is cached by the server and is never refreshed until you restart server, so changes you make will not be seen untill then. Not practical for shared webhosting.
- On Windows gettext will not allow translations to other than default language - There are some untested workarounds but they are messy (Custom Code, Thread Safe?, PHP as FastCGI not as a module)
- On Windows gettext will only read the directory that belongs to the default language meaning all translations need to go in the default local directory to allow translations.
Gettext Tutorials
Gettext Documentation
Gettext software
Misc documents
It is not straight forward to getting gettext() to workout of the box, especially when using xammp on windows. HEre I will address the issues I came across while trying to get translation to work. These issues probably also appear on diffrent setups.
When i was developing QWcrm on my windows xammp setup I would make changes to translation strings in th .PO file (via POedit) and these would not get reflected in my software. After a lot of research I discovered that when you run PHP as an Apache module the the getttext translation files upon first load are cached 'premanently' or for a time which I can not figure out. So to get around this I needed to find a way of refreshing the cache or turning it of for my development site.
Solutions I found
I will now outline my research below
Emptying of MO gettext cache without restarting apache links
These following issues can cause a real problem when devloping with gettext on windows. The main issue I came across is the localisation handling.
Issue
Solutions
You can write code to utilise the workaround outline above by address the locale issue. When trying to fix this do not forget about the caching issue above.
Links
xgettext is very particular about what it scans for, it seems to be syntax aware rather than just searching for the strings. i.e. if a line is remmed out it will ignore it.
once you have your project done you need to grab all of the strings and translate them, doing this manually would be difficult and you would miss strings. I outline the options I have found below:
Applications
Smarty TPL Scanning software
Poedit Links
Smarty Poedit Parsers (software) / and other parsers than can potentially be used
Poedit notes
Compiling all smarty templates
This section is involve in actually translating the strings in the smarty software.
Smarty translation links (various)
Smarty Software
tsmarty2c.php Command line examples
setup the software as per these instructions - configure the software, you dont need the poedit software for this to work.
In this article we will be discussing the compression of output from a php, not normal assets such as JS and css. Because the nature of PHP files is dynamic we have to use another method.
After needing to compress my PHP output for QWcrm I started researching on the internet after thinking it would just be a case of a couple of lines of code. What I discovered is there are several ways to compress PHP output and each has their pros and cons. I also found that some people were incorrectly using the wrong or outdated methods. Below I will go through each method I found and then I will sum up my thoughts at the end so you can easily workoout what method you want to use.
One other thing to note is that everyone goes on about how they gzip their content, but in these modern times there are 2 compression methos GZIP and DEFLATE, deflate being the newer method and can offer better compression.
I have discovered that on some server installs that the following code (in particular text/html) will compress PHP output. Obviously you have to have mod_deflate installed. Worth a try and add other file types as needed.
<IfModule mod_deflate.c> <IfModule mod_filter.c> AddOutputFilterByType DEFLATE text/html </IfModule> </IfModule>
Below is the normal way of compressing with deflate (gzip replacement) and the legacy gzip. I have added these for references only as it keeps coming up but will not actually compress PHP output but as a combined effect can help reduce the download footprint of the webpage and its assets.
Example 1 - Enable compression via .htaccess (mod_deflate)
This seems to be the prefered .htaccess compression method now because it gets better ratios.
<IfModule mod_deflate.c> <IfModule mod_filter.c> AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/x-javascript </IfModule> </IfModule>
Example 2 - Enable compression via .htaccess (mod_gzip)
http://www.awesomeinfolab.com/enable-gzip-compression/
I have never come across this method before in htaccess and might not work on all apache installs. I am thing of PHP as Fast-CGI/'Apache Module'
<ifModule mod_gzip.c> mod_gzip_on Yes mod_gzip_dechunk Yes mod_gzip_item_include file .(html?|txt|css|js|php|pl)$ mod_gzip_item_include handler ^cgi-script$ mod_gzip_item_include mime ^text/.* mod_gzip_item_include mime ^application/x-javascript.* mod_gzip_item_exclude mime ^image/.* mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.* </ifModule>
Links
This takes advantage of Php's buffered output and buffers all output of the script until the Php engine has completed, and then runs all the output through a special function that gzip compresses it before sending it on to the browser.
Just place this at the very top of all your PHP pages and it will send gzip-compressed output to the browsers with the correct headers.
ob_start("ob_gzhandler");
The function basically says start buffering PHP content and tag it to says the outputted content should be gzipped. The procedure should also send the correct headers so the browser knows it is compressed. I also think that unless the browser has told the server that it supports compression that the content will be returned uncompressed. All modern browsers send the 'I support compression' headers.
Some say once the script is finished it will flush the buffer and output the content automatically and that is why you can get away with 1 line, however this article from magicmonster tells you to add the flush command at the end to flush the cache.
ob_end_flush();
The method mentioned above is quick and easy, but the downfalls are that it only works on Apache with mod_gzip and according to the Php manual this is not the preferred method for gzipping.
You can increase the compression ratio by altering the php.ini or add the following to the script before ob_start("ob_gzhandler")
ini_set('zlib.output_compression_level', 4);
Another example
<?php if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start(); ?>
This example adds a check to see if the browser send the “Accept-Encoding: gzip” or “deflate” header before enabling the compression, however the buffer is still enabled even if compression is not required.
(From the Php manual at www.php.net)
note that using zlib.output_compression is preferred over ob_gzhandler().
Links
Create a buffer, fill the buffer, compress the buffer data and send the content to the client
This is similiar to ob_start("ob_gzhandler") but there is a little more to it.
Example 1
http://www.webcodingtech.com/php/gzip-compression.php
This example utilises the PHP buffer correctely and manual takes the buffered content, sends the compress data headers relevant to the compression method, then it compresses the blob before returning it to the buffer. The buffers is then dispaly or returns to the browser as compress content. I dont think this method is dependant on having Apache mod_gzip installed for the auto detection of the compression headers from the browser or to send the correct output headers.
This example has some issues an seems dated to use for compression. I think PHP has moved on. I would not use print as echo is quicker and I have no idea what print("\x1f\x8b\x08\x00\x00\x00\x00\x00"); does.
// Include this function on your pages function print_gzipped_page() { global $HTTP_ACCEPT_ENCODING; if( headers_sent() ){ $encoding = false; }elseif( strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') !== false ){ $encoding = 'x-gzip'; }elseif( strpos($HTTP_ACCEPT_ENCODING,'gzip') !== false ){ $encoding = 'gzip'; }else{ $encoding = false; } if( $encoding ){ $contents = ob_get_contents(); ob_end_clean(); header('Content-Encoding: '.$encoding); print("\x1f\x8b\x08\x00\x00\x00\x00\x00"); $size = strlen($contents); $contents = gzcompress($contents, 9); $contents = substr($contents, 0, $size); print($contents); exit(); }else{ ob_end_flush(); exit(); } } // At the beginning of each page call these two functions ob_start(); ob_implicit_flush(0); // Then do everything you want to do on the page echo 'Hello World'; // Call this function to output everything as gzipped content. print_gzipped_page();
Links
This is the prefered method for gzipping over ob_gzhandler()
The zlib extension can be used to transparently compress PHP pages on-the-fly if the browser sends an “Accept-Encoding: gzip” or “deflate” header. Compression with zlib.output_compression seems to be disabled on most hosts by default, but can be enabled with a custom php.ini file:
The zlib extension is the undelying technology and the zlib.output_compression = On is a switch that enables transparent/invisible compression on all PHP content. The zlib extension is also the library that is used for other compressions such as ob_gzhandler. I would need to check which compressions operations were covered by it.
This method is installed on most servers but left of by default. It will automatically send the output back to the client's browser in a compressed form if the 'allow compressed content' header is sent with the page request. If enabled in the php.ini then no further coding is required in any php (or other) script, or for that matter any assets.
Enable via php.ini
Add or alter the following line in the php.ini
zlib.output_compression = On
Enable via a PHP script
If zlib.output_compresssion is disabled but installed, you can enable either by editing the php.ini (as above) or you can add the following in to your PHP script. This will only enable compression for the script it is included in. and you must add this code before any headers or output is sent from the script. You should also note that having this method of compression will cause errors if further compression methods are implemented in your scripts.
if (extension_loaded("zlib") && (ini_get("output_handler") != "ob_gzhandler")) { @ob_end_clean(); @ini_set("zlib.output_compression", 1); }
As you can see this simple script makes a few checks, that the libary is present and that ob_gzhandler() has not been set. This is perhaps optional depending on your script, the ob_end_clean() just makes sure any buffers are emptied, I am not sure this is needed either. The @ symbol just surpresses errors and again these could be removed
Links
There is a difference between these 3 functions even thought they all compress a blob you supply to them. However the concesous is to use gzencode() as it outputs in the correct format including the required checksums. This function is also supports both gzip and deflate compression algorithyms.
Joomla Example
I have included this to see how these guys do it as they have more experience than me. This process happens in 2 distinct sections, the first check to see if the gzip function is enabled whilst check to see if the server supports zlib compression and that ob_gzhandler has not already been set.
/** * Execute the application. * * @return void * * @since 3.2 * * From {Joomla}libraries/cms/application/cms.php */ /** * @package Joomla.Libraries * @subpackage Application * * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ public function execute() { // Perform application routines. $this->doExecute(); // If we have an application document object, render it. if ($this->document instanceof JDocument) { // Render the application output. $this->render(); } // If gzip compression is enabled in configuration and the server is compliant, compress the output. if ($this->get('gzip') && !ini_get('zlib.output_compression') && (ini_get('output_handler') != 'ob_gzhandler')) { $this->compress(); // Trigger the onAfterCompress event. $this->triggerEvent('onAfterCompress'); } // Send the application response. $this->respond(); // Trigger the onAfterRespond event. $this->triggerEvent('onAfterRespond'); }
The second section actually does the compression and further checking, and yes there is some duplication of these checks. This fucntion supports the use of gzip or deflate compression algorithyms which is great for compatability. If you look at the code you can see that gzencode() is used and that if performs compression on a single variable (blob) rather than a page. gzencode() is able to use both algorithyms where as the other 2 functions this section covers cannot.
The code has been compress but because of the nature of the function you have to manually send the 'Content-Encoding' header so the browser knows the payload is compressed and how it has been compressed.
/** * Checks the accept encoding of the browser and compresses the data before * sending it to the client if possible. * * @return void * * @since 11.3 * * From {Joomla}libraries/joomla/application/web.php */ /** * @package Joomla.Platform * @subpackage Application * * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE */ protected function compress() { // Supported compression encodings. $supported = array( 'x-gzip' => 'gz', 'gzip' => 'gz', 'deflate' => 'deflate' ); // Get the supported encoding. $encodings = array_intersect($this->client->encodings, array_keys($supported)); // If no supported encoding is detected do nothing and return. if (empty($encodings)) { return; } // Verify that headers have not yet been sent, and that our connection is still alive. if ($this->checkHeadersSent() || !$this->checkConnectionAlive()) { return; } // Iterate through the encodings and attempt to compress the data using any found supported encodings. foreach ($encodings as $encoding) { if (($supported[$encoding] == 'gz') || ($supported[$encoding] == 'deflate')) { // Verify that the server supports gzip compression before we attempt to gzip encode the data. // @codeCoverageIgnoreStart if (!extension_loaded('zlib') || ini_get('zlib.output_compression')) { continue; } // @codeCoverageIgnoreEnd // Attempt to gzip encode the data with an optimal level 4. $data = $this->getBody(); $gzdata = gzencode($data, 4, ($supported[$encoding] == 'gz') ? FORCE_GZIP : FORCE_DEFLATE); // If there was a problem encoding the data just try the next encoding scheme. // @codeCoverageIgnoreStart if ($gzdata === false) { continue; } // @codeCoverageIgnoreEnd // Set the encoding headers. $this->setHeader('Content-Encoding', $encoding); // Header will be removed at 4.0 if ($this->get('MetaVersion')) { $this->setHeader('X-Content-Encoded-By', 'Joomla'); } // Replace the output with the encoded data. $this->setBody($gzdata); // Compression complete, let's break out of the loop. break; } } }
So that is how Joomla does compression and it should be noted that this method is probably the most compatible way of doing compression.
Links
I wrote my own function bas heavily of the Joomla function to enable gzip. In QWcrm I was able to do this becaus emy page is stored in a single varible/blob that I can manipulate.
In the main index.php I have the following code
################################################ # Page Compression # ################################################ // Compress page and send correct compression headers if ($gzip == true && $VAR['theme'] !== 'print') { $BuildPage = compress_page_output($BuildPage); }
This is the function code stored in include.php
########################################### # Compress page output and send headers # ########################################### /** * Checks the accept encoding of the browser and compresses the data before * sending it to the client if possible. * * @return void * * @since 11.3 * * From {Joomla}libraries/joomla/application/web.php */ /** * @package Joomla.Platform * @subpackage Application * * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved. * @copyright Copyright (C) 2017 - Jon Brown / Quantumwarp.com * @license GNU General Public License version 2 or later; see LICENSE */ function compress_page_output($BuildPage) { // Supported compression encodings. $supported = array( 'x-gzip' => 'gz', 'gzip' => 'gz', 'deflate' => 'deflate' ); // Get the supported encoding. $encodings = array_intersect(browserSupportedCompressionEncodings(), array_keys($supported)); // If no supported encoding is detected do nothing and return. if (empty($encodings)) { return $BuildPage; } // Verify that headers have not yet been sent, and that our connection is still alive. if (headers_sent() || (connection_status() !== CONNECTION_NORMAL)) { return $BuildPage; } // Iterate through the encodings and attempt to compress the data using any found supported encodings. foreach ($encodings as $encoding) { if (($supported[$encoding] == 'gz') || ($supported[$encoding] == 'deflate')) { // Verify that the server supports gzip compression before we attempt to gzip encode the data. if (!extension_loaded('zlib') || ini_get('zlib.output_compression')) { continue; } // Attempt to gzip encode the page with an optimal level 4. $gzBuildPage = gzencode($BuildPage, 4, ($supported[$encoding] == 'gz') ? FORCE_GZIP : FORCE_DEFLATE); // If there was a problem encoding the data just try the next encoding scheme. if ($gzBuildPage === false) { continue; } // Set the encoding headers. header("Content-Encoding: $encoding"); // Replace the output with the encoded data. return $gzBuildPage; } } } #################################################################### # Get the supported compression algorithms in the client browser # #################################################################### function browserSupportedCompressionEncodings() { return array_map('trim', (array) explode(',', $_SERVER['HTTP_ACCEPT_ENCODING'])); }
In future I will try and see if the mod_deflate option is working on other servers as this might be built into newer version of the module to treat PHP output as normal files and compress them.
This is just a simple article to references most of the simple ADOdb functions I use in QWcrm and what they do:
$smarty->assign('currency_sym', get_company_details($db));
I will use this function for the demo. This function just returns all of the company information or a single item.
function get_company_details($db, $item = null){ global $smarty; $sql = 'SELECT * FROM '.PRFX.'TABLE_COMPANY'; if(!$rs = $db->execute($sql)){ force_error_page($_GET['page'], 'database', __FILE__, __FUNCTION__, $db->ErrorMsg(), $sql, $smarty->get_template_vars('translate_system_include_error_message_function_'.__FUNCTION__.'_failed')); exit; } else { if($item === null){ return $rs->GetArray(); } else { return $rs->fields[$item]; } } }
I will be changing the line and listing the results
return $rs->GetArray();
$rs->GetArray();
Array ( [0] => Array ( [0] => QuantumWarp [NAME] => QuantumWarp [1] => 123456 [NUMBER] => 123456 [2] => The Gurking [ADDRESS] => The Gurking [3] => London [CITY] => London [4] => Greater London [STATE] => Greater London [5] => LA1 W10 [ZIP] => LA1 W10 [6] => AF [COUNTRY] => GB [7] => 123456 [PHONE] => 123456 [8] => 123456 [MOBILE] => 123456 [9] => 123456 [FAX] => 123456 [10] => [EMAIL] => [11] => £ [CURRENCY_SYMBOL] => £ [12] => GPB [CURRENCY_CODE] => GPB [13] => %d/%m/%Y [DATE_FORMAT] => %d/%m/%Y [14] => media/logo.png [LOGO] => media/logo.png [15] => [WWW] => [16] => 10 [OPENING_HOUR] => 10 [17] => 0 [OPENING_MINUTE] => 0 [18] => 17 [CLOSING_HOUR] => 17 [19] => 0 [CLOSING_MINUTE] => 0 [20] => 3.50 [TAX_RATE] => 3.50 [21] => <p>welcome</p> [WELCOME_MSG] => <p>welcome</p> [22] => <p>thanks</p> [INVOICE_MSG] => <p>thanks</p> ) )
$rs->GetRows();
$rs->GetAssoc();
Array ( [QuantumWarp] => Array ( [NAME] => QuantumWarp [0] => 123456 [NUMBER] => 123456 [1] => The Gurking [ADDRESS] => The Gurking [2] => London [CITY] => London [3] => Greater London [STATE] => Greater London [4] => LA1 W10 [ZIP] => LA1 W10 [5] => AF [COUNTRY] => GB [6] => 123456 [PHONE] => 123456 [7] => 123456 [MOBILE] => 123456 [8] => 123456 [FAX] => 123456 [9] => [EMAIL] => [10] => £ [CURRENCY_SYMBOL] => £ [11] => GPB [CURRENCY_CODE] => GPB [12] => %d/%m/%Y [DATE_FORMAT] => %d/%m/%Y [13] => media/logo.png [LOGO] => media/logo.png [14] => [WWW] => [15] => 10 [OPENING_HOUR] => 10 [16] => 0 [OPENING_MINUTE] => 0 [17] => 17 [CLOSING_HOUR] => 17 [18] => 0 [CLOSING_MINUTE] => 0 [19] => 3.50 [TAX_RATE] => 3.50 [20] => <p>welcome</p> [WELCOME_MSG] => <p>welcome</p> [21] => <p>thanks</p> [INVOICE_MSG] => <p>thanks</p> ) )
$rs->FetchRow();
Array ( [0] => QuantumWarp [NAME] => QuantumWarp [1] => 123456 [NUMBER] => 123456 [2] => The Gurking [ADDRESS] => The Gurking [3] => London [CITY] => London [4] => Greater London [STATE] => Greater London [5] => LA1 W10 [ZIP] => LA1 W10 [6] => AF [COUNTRY] => GB [7] => 123456 [PHONE] => 123456 [8] => 123456 [MOBILE] => 123456 [9] => 123456 [FAX] => 123456 [10] => [EMAIL] => [11] => £ [CURRENCY_SYMBOL] => £ [12] => GPB [CURRENCY_CODE] => GPB [13] => %d/%m/%Y [DATE_FORMAT] => %d/%m/%Y [14] => media/logo.png [LOGO] => media/logo.png [15] => [WWW] => [16] => 10 [OPENING_HOUR] => 10 [17] => 0 [OPENING_MINUTE] => 0 [18] => 17 [CLOSING_HOUR] => 17 [19] => 0 [CLOSING_MINUTE] => 0 [20] => 3.50 [TAX_RATE] => 3.50 [21] => <p>welcome</p> [WELCOME_MSG] => <p>welcome</p> [22] => <p>thanks</p> [INVOICE_MSG] => <p>thanks</p> )
$rs->GetRowAssoc();
Array ( [NAME] => QuantumWarp [NUMBER] => 123456 [ADDRESS] => The Gurking [CITY] => London [STATE] => Greater London [ZIP] => LA1 W10 [COUNTRY] => GB [PHONE] => 123456 [MOBILE] => 123456 [FAX] => 123456 [EMAIL] => [CURRENCY_SYMBOL] => £ [CURRENCY_CODE] => GPB [DATE_FORMAT] => %d/%m/%Y [LOGO] => media/logo.png [WWW] => [OPENING_HOUR] => 10 [OPENING_MINUTE] => 0 [CLOSING_HOUR] => 17 [CLOSING_MINUTE] => 0 [TAX_RATE] => 3.50 [WELCOME_MSG] => <p>welcome</p> [INVOICE_MSG] => <p>thanks</p> )
$rs->fields[$colname];
QuantumWarp
Muliple Records/Rows = $rs->GetArray(); This returns a 2 dimensional array which allows you to loop through the records which are also arrays.
Single Record/Row = $rs->GetRowAssoc(); - This returns a standard associative array.
Single Item from a column in a single Row = $rs->Fields[$colname];