Do you know the situation where you want to test a little change of a pre-tested code “on the fly” and recognize that it does not work any more? I had this situation several times. Therefore, I decided to create a “flood style” blog post where I want to summarize those moments. This “flood type” post should help to remember those situations in order to safe time and help others as well. Enjoy it!
PHP and file handling
There are two main ways to handle files with PHP. The first one are the f_* methods and the second one is a kind of summary of them. Lets start with the first one:
1 2 3 4 | $handler = fopen("test.txt","a+"); fwrite($handler, "string1"); fwrite($handler, "string2"); fclose($handler); |
“a+” opens the file (creates if it does not exist) and appends the strings “string1” and “string2” to the end of “test.txt”.
1 2 3 4 5 | $handler = fopen("test.txt","r"); while(!feof($handler)){ echo fgets($handler); } fclose($handler); |
feof() returns true when $handler points to the end of the file. fgets() reads the string and and moves the pointer.
There are a bunch of other file methods in PHP. For example, fpassthru(), fread() and finfo_file().
The second way consists of two methods that serve as a wrapper method for the methods above, like:
1 2 | file_get_contents("test.txt"); file_put_contents("test.txt","data",FILE_APPEND); |
Both methods have more parameters, like passing a context resource, but they are optional.
But be aware of using the second way. file_get_contents() reads the whole content into the memory. While it is okay when you handle smaller files, it is definetly better to use the methods of the first way when reading larger files.
Reading and Writing from/to the console
The above demonstrated file handling creates so-called streams or resources. The fopen() method can also be used for reading/writing from/to the console or FTP, like:
1 2 3 4 5 | $handler = fopen("php://stdin","r"); $input= fgets($handler); $handler = fopen("php://stdout","w+"); fwrite($handler, "This is your input: $input"); |
PHP does not execute a PDO statement
You have a SQL query which works well in your SQL editor. You want to execute it with PHP and it does nothing – literally. Well, you have maybe a typo in your statement’s prepare and bind code and want to bind parameters that does not exist in your SQL code:
1 2 3 4 5 | <?php $statement = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status=:status'); $statement->bind(":email",$email); $statement->bind(":stats",$status); $statement->execute(); |
Do you see the difference? In the statement string, there is a parameter “:status”. But I want to bind a parameter “stats” which fails. Unfortunately, PDO does not throw an exception or warning! PHP dies silently in this case. There is no exception and no errors (at least not in my environment). So, remember:
PHP has no HTTP Basic Auth credentials
Wondering why $_SERVER[‘PHP_AUTH_USER’] is not set? Maybe you are using Apache in CGI/FastCGI mode. If you can not change it, add the following command to your apache conf:
1 | SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$1 |
Converting Bits to Bytes / Megabytes / Gigabytes
Do you remember how to convert bits to bytes, megabytes or gigabytes? Well, it was a good task for me to refresh this:
1 Byte | 8 Bit |
1 Kilobyte | 1024 Byte |
1 Megabyte | 1024 Kilobyte |
1 Gigabyte | 1024 Megabyte |
1 Terabyte | 1024 Gigabyte |
1 Petabyte | 1024 Terabyte |
Ok, so that is, if you have a 32 bit integer, you have 232 (or 4,294,967,296) distinct integers. A string character has 4 bytes. Therefore, the string “dogan” has 5 bytes.
If you have 1GB (or 8,589,934,592 bits) space, you can fit the 32 bit integers twice. The string “dogan” would fit 214,748,365 times in 1 gig 🙂
Recursive Problem Solution
Solving recursive problems is an art in itself and requires a seperate blog post 🙂 However, I want to summarise a bit.
Before you start to think about the problem, STOP trying to capture the whole problem! You will definetly fail. It is definetly not possible to keep all the branches in your mind. Instead, do the following:
- Think about a base case/break condition
- which condition has to be true in order to stop the recursion? This is usually something like “a collection has no more elements” or “x is greater than y”
- Do the desired operation
- usually something like add one more element from the input to the result
- Call the method with different methods with different parameters
- it is urgent that you call the method with different parameters since otherwise the method will do the same operations again and again. This will result in an infinite loop
- different parameters means usually something like increasing a counter or slicing a collection
You will usually have an array or an object as your result (step 2). Try to pass the result object as an reference to each recursive call. Doing this, you do not need to merge the result value of each recursive call with your already available result. Further, you are operating on the same object and do not allocate memory on each call.
Get the difference of two arrays
Imagine you have two arrays and they are structured with an integer as the key and a boolean as the value (HTML checkboxes, for example). You want to know the difference between two arrays: Are there new key-value pairs? Do any key’s value changed? How do you do that? Here is my solution:
1 2 3 4 5 6 7 8 9 10 11 12 | $array = [1 => true, 4 => true, 6 => true, 7 => true]; $array1 = [1 => false, 2 => true, 5 => true, 6 => false, 9 => true, 10 => false]; $result = getArrayChanges($array, $array1); print_r($result); function getArrayChanges(array $array, array $array1): array { $result = []; foreach ($array1 as $k => $v) { if (isset($array[$k]) && $v === $array[$k]) continue; $result[$k] = $v ? "add" : "remove"; } return $result; } |
and the result:
1 | Array( [1] => remove [2] => add [5] => add [6] => remove [9] => add [10] => remove) |
Getting the second highest value in an array
I am a little bit proud about what the following code does 😄https://gist.github.com/doganoo/f2d7bc6533313b665c97db12ff5c97d8
Does array contain a sum
Sometimes we just need to know whether a (numeric) array can build with its given numbers a target sum. Let’s imagine we have the array [10,20,30,40,50] and the target sum 100. We can see that 10 + 40 + 50 and 20 + 30 + 50 equal both to 100. The following code demonstrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function arraySumAvailable(array $numbers, int $val):?array{ $size = count($numbers); if($size < 3) return null; $sum = 0; $collection = []; for($i = 0;$i<$size;$i++){ for($j=$i+1;$j<$size;$j++){ for($k=$j+1;$k<$size;$k++){ $sum = $numbers[$i] + $numbers[$j] + $numbers[$k]; if($sum === $val){ $collection[] = [$i, $j,$k]; $sum = 0; } if($sum > $val) continue; } } } return $collection; } |
Bootstrap Modal does not open a second time
The following code does not execute twice (after you have opened and closed the modal once and want to open it again):
1 | $('#myModal').html(data);$("#myModal").modal({ "show": true }); |
If you get the following error in your JS console:
TypeError: $(…).modal is not a function with bootstrap Modal
It could possibly because you include all your JS stuff twice as stated here.
Throttling and the idea behind
Have you ever asked yourself how Facebook and/or Twitter load their timelines dynamicly without having any performance issues (Well, we’ll forget out all the servers around the world)? You are scrolling through your timeline and the content loads usually within a few seconds. How is that possible?The answer is “throttling”: On the web UI, any JavaScript code listens for an event (scrolling, clicking, etc). But each scroll event fires an action (content loading) which would cause many requests within a small amount of seconds. You can limit this by setting a timeout, like:
1 | function _throttle(func, delay) {<br> console.log("throttling");<br> var timer = null;<br> return function () {<br> if (!timer) {<br> timer = setTimeout(function () {<br> timer = null;<br> console.log("executing throttle fnction!");<br> func();<br> }, delay);<br> } else {<br> console.log("can not execute since throttle timeout has to be exceed");<br> }<br> }<br>} |
See the full example on GitHub.
Databases
The following section describes some interesting things / queries about databases and SQL. I use MySQL, if not otherwise said:
- Get the second highest salary:
- querying the highest salary from a table is easy (simply order by the salary column and limit to one). But what is about the second highest? Well, easy as well:1SELECT e.salary as SecondHighestSalary from employee e order by e.salary desc limit 1,1; # indices start at 0
- querying the highest salary from a table is easy (simply order by the salary column and limit to one). But what is about the second highest? Well, easy as well:
- How would you return null (instead of nothing) if the query results an empty data set?
- using the query above, we can simply add a
union null
to the query in order to reach this goal:1select e.salary as SecondHighestSalary from Employee e union select null order by SecondHighestSalary desc limit 1,1;
- using the query above, we can simply add a
Some keywords
I hear and read a couple of keywords repeadeatly. I want to summarize them here because most of them are just “fresh and fancy” buzzwords:
- Polling: a process that tests repeadetly whether a condition is true or not. In computer science, it would be a threat/process that runs after defined time units.
Some Useful Links
if you want to understand how the internet works check out this page. It is a little outdated but still very current.
Last Update: 05/07/2024. Change Description: Added Useful Links
Linux Related Issues
I recently bought a Linux Home Server with Debian. The WiFi Drivers for BroadCom BRCM43455 were missing.
The following steps enable WiFi on your device:
- install firmware-brcm80211 from here.
- if you can not install with apt-get install firmware-brcm80211, you need to add the nonfree sources to your /etc/apt/sources.list file as described here or simply download the package and install it from the local file.
- Follow the steps described here.
- find the brcmfmac43455-sdio.txt file here.
Fail2Ban and Apache 404
Everyone running an own (virtual) server knows this problem: some random guys around the globe want to check your server for vulnerabilities and sends repeated requests to your server. Most of them end as 404 requests since the requested resources are not available (at least not under the requested URI).
Luckily, we can utilize fail2ban to ban every IP address which fails. To use fail2ban, you need first to install it:
1 | # sudo apt-get install fail2ban |
Then, you need to specify a filter for the access log files, something like
1 2 3 4 5 | # Fail2Ban filter for catching 404 responses. [Definition] failregex = ^<HOST> - .* "(GET|POST|HEAD).*HTTP.*" 404 .*$ ignoreregex = .*(robots.txt|favicon.ico|jpg|png) |
in /etc/fail2ban/filter.d/apache-404.conf. Finally, you need to register your rule and filter in/etc/fail2ban/jail.local like:
1 2 3 4 5 6 7 8 9 10 11 | # # HTTP servers # [apache-404] enabled = true port = http,https filter = apache-404 logpath = /var/log/apache2/*access*.log maxretry = 6 findtime = 10m bantime = 10m |
Usually the jail.local file does not exist and has to be created manually. Technically, the jail.conf file could also be used but the fail2ban developers state clearly that the file can be overwritten by updates and it is best practice to not change the content.
Further, notice the logpath of our rule. If you have several vhosts on your server and do not want to add them manually to fail2ban, you should simply wildcard the access log path.