Skip to content.

For users of screen readers, depending on the screen resolution, the two checkboxes are for opening and closing the side menus that appear to the left and right of the screen. This is designed both for large screens and for mobile devices with a touch screen. Checking either the main menu or sidebar checkboxes causes the menu to open from the left or right side of the screen, respectively. Clearing the checkox in either the main menu or sidebar closes the menu. The checkboxes are visible to screen readers such as JAWS and NVDA for Windows, Voiceover for Mac, and Orca screen reader for Linux. When a screen reader says "clickable" for both main menu and sidebar, that is for the respective checkboxes. End of explaination.

Category: The World of Computers

Who is the Weakest Link In a Cybersecurity Chain? We Are!

I watched the video about whether the ransomware can be stopped and I scrolled down through the comment section. While reading comments, some people are suggesting that we switch to Linux because Linux is more secure compared to Windows. That is true that Linux is inherently secure compared to Windows and Mac; however, what if I were to tell you that if you are running Arch Linux, Fedora, Ubuntu, Solaris, FreeBSD, OpenBSD, Haiku OS, or just about any other operating systems in our planet that you can still fall victim to phishing attacks? If we all switch to a different operating system on a basis that one is more secure compared to other operating systems, then we are forgetting about our weakest link.

Let me ask you again. Who or what is the weakest link in the cybersecurity chain? It’s not Windows; we are the ones that need education so we can protect ourselves online.

No anti-malware, anti-virus, and anti-ransomware programs will protect you against ransomware attacks. And Linux and BSD operating systems won’t protect you from phishing emails either. What we need is cybersecurity awareness training. Businesses should establish cybersecurity awareness training. Here’s one example that shows a video about cybersecurity awareness training from Burgi Technologies. The video starts with email, which talks about safeguarding your email such as phishing, email attachments, and spam. Do note though that an email address can be spoofed, so if you receive a phishing email and the email address in the From field ends in @paypal.com and the email claims to be from PayPal, you should simply go to PayPal’s website and check what is going on in your PayPal account. Plus, the security awareness training talks about passwords, malware (don’t forget that malware can target Linux computers as well), public Wi-Fi, and even IoT, such as thermostats, Google Nest cameras, and even light bulbs. Even a router needs to be protected as well. And don’t forget about social engineering as well.

Remember what I mentioned about PayPal? Phishing attacks is one of them. They can even call you over the phone by impersonating that someone is your employer. They might say it’s urgent and they need access to the username and password so they can access the network resources so they can do harm. In other words, they can manipulate you into disclosing confidential or sensitive information.

Regarding security question and answers, it’s convenient if you forget your password, but put in your correct information and once an attacker can scour the Internet tin order to look for information, they can click the “reset password” link, fill in the answers to questions, and once everything is correct, they can then reset the password so you cannot access your account any longer. This is where a password manager comes in. Your password manager of choice can remember gibberish answers to questions. For example:

  • Question: What is your boyfriend’s name?

    Answer: I would like to say thank you to my friend 68dagbbzpTmR5.

  • Question: What is your first car you owned?

    Answer: My beautiful-looking car is my bicycle and I love jverw89.TmZr

  • Question: What is your mother’s maiden name?

    Answer: oi9574bn8tTv8rBz0qpM.,[23w489hZm

A lack of honesty can safeguard your account against information gathering so they can do harm to your account. That’s why a password manager such as Bitwarden can come in handy so that a password manager can help remember your gibberish answers to security questions. And no, security questions is not a security feature. If I know so much about you and I know your email address, I can gather information about you and reset your password by answering security questions without your knowledge. I know this is scary, but don’t let that scare you if you are using a password manager.

To take it a step further, I also make use of unique email addresses as aliases. I do not use plus addressing or catchall because I can create email addresses for my own domain name. I use different email addresses for different sites that I sign up for. For example, I gave pizzahut(at)example(dot)com to Pizza Hut, uber(at)example(dot)com for Uber, walmart(at)example(dot)com for Wal-Mart, bestbuy(at)example(dot)com, and so on and so forth. Not only is this good for security, unique email addresses enhances my privacy. Sure, this is not part of cybersecurity awareness training as employees may not have the luxury of having more than 1 email addresses, but I did this in order to take security into my own hands so that I won’t become a weakest link in the cybersecurity chain. Even if businesses said that they took security seriously, if one of my unique email addresses have been compromised in a breach and ends up in Have I Been Pwned, not only should I change the password using my password manager, I can change my email address right away. Why? I did this in order to dodge spam and phishing emails. Because I make use of unique email addresses, I get very little to no spam each month. If I do get spam email messages that lands in my spam or inbox folder and one of my unique email addresses were listed in the To field, I can consider my email address compromised and can track who sold or give away my email address and change my email address or stop doing business with them at any time, immediately delete my compromised email address, and move on with my life.

Don’t let Linux users tell you that you should switch to Linux no matter how inherently secure Linux is. At the end of the day, no matter how much we need to keep our operating systems and software up to date, we still are the weakest link in the cybersecurity chain. We still need to educate everyone in order to stay safe online. Linux is not a be-all-end-all solution to our security problems.

Refresh Your Browser Cache On a Regular Basis

Trying to Sign In to My Account at Pizza Hut’s Website…

While trying to sign into Pizza Hut’s website, I was having difficulty with trying to login after I click “I am not a robot.” Once I click “Sign In,” the login page got stuck and I had to wait until I see something like “CAPTCHA expired” or something and I did this so many times to no effort. I closed Firefox, moved my .mozilla directory to .mozilla.bak directory, started Firefox, and tried to sign in to my Pizza Hut account as usual. Initially, I did receive “Something went wrong, try again” message, but once I sign in, everything is fine. I then ordered my pizza as usual. After that, I moved my new .mozilla directory to .mozilla.fresh directory and restarted Firefox to get my old profile back. For non-Linux users, the . (dot) signifies a hidden directory, such as .mozilla (dot mozilla for screen reader users) and .config (dot config).

One of the troubleshooting steps I’ve tried is to clear the browser cache, which are temporary files that are stored in a computer for later retrieval, such as HTML files, images, and CSS files (cascading stylesheet for non-Web developers). Sometimes, the cached version of the files get corrupted. To solve the problem, follow the steps below.

Firefox

  1. In Firefox, open the Settings menu from the Edit menu (Alt+E, N). For sighted users, the Settings menu (beneath Zoom) can be found by navigating to the hamburger (≡) menu.
  2. In the Privacy and Settings section, navigate to Cookies and Site Data.
  3. Open the Clear Data… dialog.
  4. (Optional) In the Clear Data dialog, uncheck the check box for Cookies and Site Data if you want to stay signed in to websites you frequently visit.
  5. Navigate to the Clear button and confirm that you want to clear all the cached files.
  6. Give Firefox a fresh restart and you should be good to go.

Chrome

Clearing the browser cache can be found in the Security and Privacy section of the Settings page. I’m a partially-sighted user and I’m not sure how I can navigate to the Settings page if I’m using only a keyboard and a screen reader.

Summary

Hopefully you should be able to sign in to Pizza Hut’s website. I have encountered no problems with other websites besides Pizza Hut, but every now and then, I think it makes sense to clear browser cache during a monthly or weekly basis. The only reason I need to refresh the cache is while working in my website. I still get a “something went wrong” message when I try to sign into my account at Pizza Hut’s website, but after I try to sign in again, it worked. I do not like pointing fingers, but I think something must be wrong with Pizza Hut’s website.

Anyway, I hope I can be of much help. Happy surfing and stay safe online.

New CSS Property For Web Developers: backdrop-filter

While browsing through Twitter as a progressive web application in my Android smartphone, I saw the blur effect in the header of the Twitter page. I like what I saw, so I did a search and came across backdrop-filter, which only work with Chrome-based browsers at the moment and Firefox does not have support for it. For those with eyesight, here’s what it looks like:

An image of my website running in Google Chrome with a blurred background for articles.
This image shows a website running in Google Chrome. Google Chrome supports a backdrop-filter property with a blur radius set to 5 pixels.

Mozilla Firefox (as of 96) does not support backdrop-filter CSS property.

An image of my website running in Mozilla Firefox with no blurred background for articles.
This image shows a website running in Mozilla Firefox. Firefox does not support a backdrop-filter property.

An example of how the backdrop-filter property is shown below:

main article {
  backdrop-filter: blur(5px);
}

Until Firefox supports the backdrop-filter filter right out of the box, I’m going to leave it off for now so both major browsers look the same.

Internet and Safety: Why Physical Businesses Should Not Require Everyone To Use Internet?

(For my blog post, I want to focus on the audience regarding people who use Internet every single day and knows a lot about cybersecurity. Myself included.)

Imagine a scenario: you went to get your haircut and the place you went to requires you to enter an email address before you get your haircut. Why? Even if I do have a smartphone and I use Internet every single day, why must I put in my email address? For what purpose? To send spam? For businesses, they might say “we respect your privacy and take security seriously,” but in my mind, I would say that if an email gets compromised in a data breach, it’s more likely that those who are not tech-savvy are more likely to receive spam and phishing emails. Not thinking about security when using the Internet can lead to ransomware and identity theft. They might stop using the computer altogether because of fear of feeling unsafe online.

Okay, so I can imagine people asking…

What is ransomware?

So anyone who have not used the Internet before would then ask…

Okay, so what is malware? Oh, maybe I should click in the link. Oh, and what is a file?

Okay, I can imagine tech-savvy folks asking “what do you mean, ‘what is a file?’ Do you ever know how to use a computer before?” How can we guide people who does not use Internet every single day, let alone not knowing “what is an Internet?”

What is an operating system? Windows? Mac? Linux? What is an email address? What is a “file?” See where I’m going with? What is Android? iPhone? iOS? How do I manage files and folders in my computer? How do I check my email? I hope you get my point.

So back to the topic about email address requirement, people who have no plans to educate themselves regarding security and privacy should not have an email address and should not be using the Internet. Even a smartphone can be very complex compared to a cell phone that only make and receive phone calls and nothing else. Let alone how to send and read text messages. And yes, I’m talking about people who use cell phones with no capability for browsing the Internet. Not even Firefox, Chrome, or Safari.

Okay, so you say that your 90-year-old grandmother knows how to use the Internet, takes care of security themselves, and I should not overly-generalize myself. Well, that’s great. People should be educated regarding the implications regarding cyber attacks and how to protect themselves; however, as long as people out there (Demographics of Cybercrime Report) do not take their time to educate and protect themselves, businesses should not require them to have an email address when they check in. Even dentists should make email address requirement optional as well. Even though I have close to 200 email addresses (one email address per site with no plus addressing and no catchall for my domain), I do not want to enter my email address if I do not want to for privacy and security reasons.

Businesses say “we take security and privacy seriously,” yet businesses do not take their time to harden and patch their systems over time. Of course, training employees regarding how to protect themselves against phishing emails is a very important part of having a security culture for businesses. But then again, an email address would be a requirement for businesses for getting your customers to setup an account online, but in a physical world where people simply walk in, as long as people do not use the Internet and do not plan to educate themselves, an email address should not be a requirement. At all.

My Dream Home of the Future: Computer in Server Closet; KVM in Home Office; Home Theater

I have been watching a couple of YouTube videos of people who want a computer in one room (such as a wiring closet) and a keyboard, video, and mouse (KVM) in a home office. To give you an idea of what I’m talking about, I want to post links to YouTube videos.

Embedding YouTube or Odysee videos will insert a tracking cookie in users’ personal computers. As a citizen of the US, I need to follow GDPR if European visitors visit my website. I don’t like and want to talk to lawyers to be honest. 🤣😀

As for the video from Linus Tech Tips, I would much rather have a couple of computers rather than single computer that can house a couple of virtual machines running desktop OSes such as Linux and Windows just to make it easier for me. So yeah, a virtual machine is a computer within a computer that can serve different purposes such as running Ubuntu within Windows using VirtualBox or by running Windows OS in a Linux host using KVM or Xen.

(more…)

Mic Comparison: Shure MX185 Cardioid vs Movo LV8-D Omni-Directional Lavalier Microphone

Here’s a link to a video in Odysee:

Mic Comparison: Shure MX185 Cardioid vs Movo LV8-D Omni-Directional Lavalier Microphone

Embedding any videos from any external sources will insert tracking cookies in your computer or mobile device so I decided to link a video instead. Even in the US, I have to comply with Europe’s GDPR as I want to allow all visitors to visit my site. Inserting any kind of tracking cookies is against my privacy policy. I would like to upload my videos to my website; however, videos take up a lot of space and that’s why I uploaded my video regarding the mic comparison to Odysee.

This is a comparison of two lavalier microphones. Recently, I bought a Shure MX185 cardioid lavalier microphone as I want to test if a uni-directional (cardioid) microphone is right for me, especially if I want to test and hear if my AKG K702 headphone leaks sound to my microphone especially for the Zoom meeting. I bought a Movo LV8-D microphone as of late October so I can participate in Zoom meeting that began November of last year. The Zoom meeting I am participating in is Cisco Academy from National Industries for the Blind. I’m studying for Cisco Certified Network Associate certificate (CCNA, for short) and my class ends by the end of August. I asked if students and my instructor can hear any leaks coming from my K702 headphone and they said they did not hear any leaks at all, which is great. However, I have a Sony WX1000XM3 headphone and because of the shape of my headphone, I don’t think my hearing aids are picking up any high frequency sounds unlike when I use my AKG open-back headphone.

I plan to ship my Shure microphone back because the uni-direction nature of a lavalier microphone is not for me, especially as I was reading from left to right as i read the script during the recording.

Do note that even though I did cut out a couple of pauses in my audio production software (Ardour), I tend to speak slow as speaking at a moderate speed for more than a minute is not my second nature. As I live in Altha, FL, a rural town in the United States, I’ve been very lonely a lot even when I go to restaurants with my family. Plus, I did not position the text inside the dialog in the first part of the video correctly. I do not want to waste another 45+ minutes trying to render the entire video using Blender. Although as a Linux user, I could have used KDenLive instead of Blender; however, as Blender is a very easy tool for me to use, I used it for the majority of my video editing. My familiarity with KDenLive is secondary to Blender.

When I zoom in using GNOME Magnifier (Windows key+Alt+8 to activate the magnifier and Windows key+Alt+- or Windows key+Alt+= to zoom in or out, respectively), there is a small mouse cursor shown in the screen. I think it’s a bug with the compositor that draws the entire application, be it Firefox, GIMP, or Ardour). Please ignore the small mouse cursor. Thanks.

Anyway, I appreciate you checking out my video that I linked above. Here are the links to products listed for the video:

New Addition To My Website: Pagination

As a web developer of my website, I have implemented pagination that allows anyone to view more posts by page and be able to view blog posts by month and year. I created a custom theme from scratch so that I can personalize my website to my liking. I wanted to give the pagination system an “electronic” look.

Pagination along with month and year for my website
This screenshot shows pagination implemented in my website. In my development machine, I have set the number of posts per page to 5 in order to demonstrate the effect. I blurred the surrounding image to cut the file size by half.

For those with eyesight, you can click in the image to see a full screen of my desktop that shows the pagination system in effect.

Here’s the code if any web developers want to implement it into their WordPress/ClassicPress website. I grabbed and modified the code from the kriesi.at website and once I got it done, I then wanted to add a month/year functionality into my pagination system. Even though I did seek help from the ClassicPress forum in my thread regarding getting the latest archive in an array instead of a link, I was able to do it myself with the help of this webpage that contained the function called wp_get_archives(). Here is a code taken from the wordpress.org site.

if ( 'monthly' == $r['type'] ) {
    $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`,"
        ." count(ID) as posts FROM $wpdb->posts $join $where"
        ." GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date $order $limit";
    $key = md5( $query );
    $key = "wp_get_archives:$key:$last_changed";
    if ( ! $results = wp_cache_get( $key, 'posts' ) ) { 
        $results = $wpdb->get_results( $query );
        wp_cache_set( $key, $results, 'posts' );
    }   
    if ( $results ) { 
        $after = $r['after'];
        foreach ( (array) $results as $result ) { 
            $url = get_month_link( $result->year, $result->month );
            /* translators: 1: month name, 2: 4-digit year */
            $text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $result->month ), $result->year );
            if ( $r['show_post_count'] ) { 
                $r['after'] = ' (' . $result->posts . ')' . $after;
            }
            $output .= get_archives_link( $url, $text, $r['format'], $r['before'], $r['after'] );
        }   
    }   
}

So I looked over the code and I saw that there is a $result variable that is converted into an array. I took that code from the WordPress.org website and I modified the code to suit my needs in functions.php inside my custom theme folder.

function monthly_archive_array() {
    global $wpdb;
    $r['type'] = 'monthly';
    $where = apply_filters( 'getarchives_where',
        "WHERE post_type = 'post' AND post_status = 'publish'", $r );

    $last_changed = wp_cache_get( 'last_changed', 'posts' );
    if ( ! $last_changed ) {
        $last_changed = microtime();
        wp_cache_set( 'last_changed', $last_changed, 'posts' );
    }

    /**
     * Filter the SQL JOIN clause for retrieving archives.
     *
     * @since 2.2.0
     *
     * @param string $sql_join Portion of SQL query containing JOIN clause.
     * @param array  $r        An array of default arguments.
     */
    $join = apply_filters( 'getarchives_join', '', $r );
    
    $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date ASC";
    $key = md5( $query );
    $key = "wp_get_archives:$key:$last_changed";
    if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
        $results = $wpdb->get_results( $query );
        wp_cache_set( $key, $results, 'posts' );
    }
    if ( $results ) {
        return (array)$results;
    }
}

$archiveMonthlyList = monthly_archive_array();

function get_monthly_archive_array() {
    global $archiveMonthlyList;
    return $archiveMonthlyList;
}

Note that in the last 6 lines of code, I decided to have a function (get_monthly_archive_array()) get the result from a variable ($archiveMonthlyList). When I go to my website, ClassicPress executes a functions.php file in my custom theme folder so that I don’t get the data from the database twice. Yet I actually do have wp_get_archives() in my sidebar, so I did have my website execute the same SQL statement twice. Well, one is in descending order from the newest to the oldest in the sidebar and I wanted to get the month and year of all the published posts from oldest to newest. If I replace the built-in function in my sidebar with my own function which exposes an array, I should be able to improve performance for my website, although probably not by much.

function constructLinkFromYearMonth($array, $index, $nextMonth) {
    $offset = ($nextMonth === true) ? 1 : -1;
    $spanlsaquote =  ($offset === -1) ? "<span class='visualonly'>‹ </span>" : "";
    $spanrsaquote =  ($offset ===  1) ? "<span class='visualonly'> ›</span>" : "";
    $prevNextMonth = ($offset === -1) ? "Previous" : "Next";
    echo "<a href='".get_month_link($array[$index + $offset]->year,$array[$index + $offset]->month )
        ."'>".$spanlsaquote."<span class='screenreader'>".$prevNextMonth." month: </span><span class='narrow-screen'>"
        .showMonthYearLocale(
        [$array[$index + $offset]->year,$array[$index + $offset]->month])."</span>".$spanrsaquote."</a>";
}

function show_pagination() {
    global $paged;
    if(empty($paged)) $paged = 1;
    
    global $wp_query;
    $pages = $wp_query->max_num_pages;
    if(!$pages)
    {
        $pages = 1;
    }

    echo "<div class='pagination'>";
    echo "<h3>View More Posts By Month or Page</h3>";
    echo "<div class='pagination_area'>";

    echo "<div class='pagination_top'>";

    // Get the list of months and years from the archive in an array.
    $monthlyArchive = get_monthly_archive_array();
    // If there is year/month in URL, get it and trim the leading and
    // trailing slashes. Example: 2021/04
    $currentMonthYear = trim($_SERVER['REQUEST_URI'],'/');
    // array[0] = year, array[1] = month
    // Example: array[0] = "2021", array[1] = "04"
    $curMonthYearArray = explode('/',$currentMonthYear);
    if(preg_match("/^[0-9]{4}\/(0[1-9]|1[0-2])$/",$curMonthYearArray[0].'/'.$curMonthYearArray[1])) {
        // array[0] = year, array[1] = month
        // Example: array[0] = "2021", array[1] = "04"
        $curMonthYearArray = explode('/',$currentMonthYear);
        // Initialize a blank array for integers.
        $intCurMonthYearArray = Array();
        // Convert strings to integers in an array in a new variable.
        foreach($curMonthYearArray as $curMonthYear)
            $intCurMonthYearArray[] = (int)$curMonthYear;
        // Initialize the integer for the index.
        $indexOfMonthYearArray = 0;
        foreach ($monthlyArchive as $key => $val) {
           if ((int)$val->year === $intCurMonthYearArray[0] &&
               (int)$val->month === $intCurMonthYearArray[1]) {
               $indexOfMonthYearArray = $key;
           }
        }

        echo "<ul class='pagination_month'>";
        echo "<li class='month_current'>";
        echo "<span>".showMonthYearLocale($curMonthYearArray)."</span>";
        echo "</li>";
        if($indexOfMonthYearArray > 0) {
            echo "<li class='month_prev'>";
            constructLinkFromYearMonth($monthlyArchive, $indexOfMonthYearArray, false);
            echo "</li>";
        } else echo "<li class='month_prev smallfontsize'><a class='screenreader'>Beginning of current month</a></li>";
        if($indexOfMonthYearArray + 1 < count($monthlyArchive)) {
            echo "<li class='month_next'>";
            constructLinkFromYearMonth($monthlyArchive, $indexOfMonthYearArray, true);
            echo "</li>";
        } else echo "<li class='month_next smallfontsize'><a class='screenreader'>End of current month</a></li>";
        echo "</ul>";
    } else {
        $latest = $monthlyArchive[count($monthlyArchive) - 1];
        echo "<div class='pagination_month msg'><span>View latest posts since "
            ."<a class='date-narrow' href='".get_month_link($latest->year,$latest->month )
            ."'>".showMonthYearLocale([$latest->year,$latest->month])."</a>.</span></div>";
    }

    echo "</div>";

    if(1 != $pages)
    {
        echo "<div class='pagination_bottom'>";
        echo "<div class='pagination_prevbtns'>";
        if($paged > 2)
            echo "<a href='".get_pagenum_link($paged - 2)."'>«</a>";
        else echo "<a class='visualonly pagination_disbtn'>«</a>";
        if($paged > 1)
            echo "<a class='pageprev' href='".get_pagenum_link($paged - 1)."'>‹</a>";
        else echo "<a class='pageprev visualonly pagination_disbtn'>‹</a>";
        echo "</div>";

        echo "<ul class='pagination_slot'>";
        for ($i=1; $i <= $pages; $i++)
        {
            echo "<li>";
            echo ($paged == $i)? "<a class='pagination_number current'><span class='screenreader'>Current Page: </span>".$i."</a>":"<a href='".get_pagenum_link($i)."' class='pagination_number' >".$i."</a>";
            echo "</li>";
        }
        echo "</ul>";

        echo "<div class='pagination_nextbtns'>";
        if ($paged < $pages)
            echo "<a class='pagenext' href='".get_pagenum_link($paged + 1)."'>›</a>";  
        else echo "<a class='pagenext visualonly pagination_disbtn'>›</a>";
        if ($paged < $pages-1)
            echo "<a href='".get_pagenum_link($paged + 2)."'>»</a>";
        else echo "<a class='visualonly pagination_disbtn'>»</a>";
        echo "</div></div></div></div>\n";
    } else {
        echo "<div class='pagination_bottom'>";
        echo "<div class='pagination_prevbtns'>";
        echo "<a class='visualonly pagination_disbtn'>«</a>";
        echo "<a class='pageprev visualonly pagination_disbtn'>‹</a>";
        echo "</div>";
        echo "<div class='pagination_slot msg'><span class='nopages'>Only 1 page shown.</span></div>";
        echo "<div class='pagination_nextbtns'>";
        echo "<a class='pagenext visualonly pagination_disbtn'>›</a>";
        echo "<a class='visualonly pagination_disbtn'>»</a>";
        echo "</div></div></div></div>\n";
    }
    
}

function monthly_archive_array() {
    global $wpdb;
    $r['type'] = 'monthly';
    $where = apply_filters( 'getarchives_where',
        "WHERE post_type = 'post' AND post_status = 'publish'", $r );

    $last_changed = wp_cache_get( 'last_changed', 'posts' );
    if ( ! $last_changed ) {
        $last_changed = microtime();
        wp_cache_set( 'last_changed', $last_changed, 'posts' );
    }

    /**
     * Filter the SQL JOIN clause for retrieving archives.
     *
     * @since 2.2.0
     *
     * @param string $sql_join Portion of SQL query containing JOIN clause.
     * @param array  $r        An array of default arguments.
     */
    $join = apply_filters( 'getarchives_join', '', $r );
    
    $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date ASC";
    $key = md5( $query );
    $key = "wp_get_archives:$key:$last_changed";
    if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
        $results = $wpdb->get_results( $query );
        wp_cache_set( $key, $results, 'posts' );
    }
    if ( $results ) {
        return (array)$results;
    }
}

$archiveMonthlyList = monthly_archive_array();

function get_monthly_archive_array() {
    global $archiveMonthlyList;
    return $archiveMonthlyList;
}

The reason why I decided to remove the range variable is so I want viewers in mobile devices to be able to scroll through pages horizontally (left/right). Of course, for desktop users I could add some JavaScript code that allows me to add/remove numbers based on the current page number and based on the width of the web browser. However, I am a heavy proponent of not using JavaScript whenever possible. I want everyone without JavaScript or for those such as me who use NoScript to enjoy the full potential of my website.

Web development is hard work, but at the end of the day, I enjoyed it a lot. Thanks for reading and enjoy visiting my site!

And note to self: I need to encode HTML code even if it’s inside a <pre> tag before I break my website when publishing my post. Don’t forget to do the same if you are a web developer as well. Use &lt; for < and &gt; for >. You can also use &quot; for " as well. View the source code for my post to see what I did. In Firefox, open the context menu and choose “View Page Source.” Same goes for Google Chrome.

Updated as of July 3, 2021 at 12:44 AM: Added <wbr /> tag to a long function in order to break the function into two lines. This is useful for mobile devices. All today’s mobile devices should support HTML5 by now.

How To Create a New User in pfSense and VyOS?

When you setup your new router, it’s always a good idea to create a new user other than admin for pfSense and vyos for VyOS in order to reduce the chance that bots and miscreants will gain access to your router.

VyOS

Here’s the completed configuration of my VyOS router and I will show you the commands.

Configuration
service {
    # ...
    ssh {
        access-control {
            allow {
                user <username>
                user vyos
            }
        }
        listen-address 10.249.0.1
    }
}
system {
    # ...
    login {
        banner {
            pre-login "Unauthorized access is strictly prohibited."
        }
        user <username> {
            authentication {
                encrypted-password ****************
                plaintext-password ****************
            }
            full-name "First and last name goes here."
            home-directory /home/<username>
        }
        user vyos {
            authentication {
                encrypted-password ****************
                plaintext-password ****************
            }
        }
    }
# ...
}
Commands
ssh vyos@10.249.0.1
configure
edit system login user <username>
set authentication plaintext-password <your-password-goes-here>
set full-name "First and last name goes here."
set home-directory /home/<username>
exit
edit service ssh access-control
set allow user <username>
set allow user vyos
commit
save

You want to allow vyos access using SSH to make sure it works. Also, there is encrypted-password in VyOS but VyOS gave me an error telling me that the encrypted password is invalid. I did try to discard, but VyOS told me there are not changes to be discarded, so I saved, started a new terminal window, and once I SSH into my VyOS router for 10.249.1.1, everything works fine.

Now don’t exit out of VyOS session just yet. You want to make sure SSH is working properly for a user you want to log into. Because otherwise editing and viewing the configuration will have to be done either through the use of a console cable or a monitor and keyboard hooked up to a monitor. SSH using your new username and password you’ve created. If you can successfully login to VyOS with a different username, you can simply remove the vyos user from the access control list in configuration mode.

delete service ssh access-control allow user vyos

Again, stay logged in to VyOS and use a different terminal to test and make sure you can log into VyOS through SSH. If everything is working as intended, you can safely log out of VyOS from all the terminals you’ve opened.

Also, you can configure a banner. Examine the configuration above and see if you can add a login banner. The pre-login is for when a user attempts to access the VyOS router using SSH. This will print out a banner before a user gets prompted for a password. After a user logs into VyOS, if the post-login is set, VyOS will print out the banner once the user logs in. This concludes the commands used for securing VyOS.

pfSense

The same can be done for pfSense. Open the web browser, point your browser to pfSense (in my case, http://10.249.2.1), and login to your pfSense web interface. Once you get to the main interface, follow instructions as follows.

  1. In the System menu, open the User Manager.
  2. Click in the + Add button below the list of users.
  3. Enter the Username, Password, and Full Name. No spaces in the username.
  4. In the Group Membership area, select admins and click in Move to “member of” list. This will move the admins group to the “member of” list.
  5. Save the changes, log out, and log back in as the new admin user you have created in step 4.
  6. In the user manager, click in the pencil icon (Edit) to edit the admin user.
  7. Check the checkbox for Disabled. An admin user cannot login once the checkbox is selected.
  8. When done, Save the changes.

Try to login as admin. If successful, you should not be able to log in as an admin user but instead log in as a new user. This concludes the step-by-step instructions for pfSense.

Conclusion

Preventing a root or admin user from logging into a router is one of the security’s best practices. You can help ensure that bots and miscreants won’t be able to gain access to your router without the correct username and password. Even when bots are performing a brute-force attack. Still, it’s important to restrict access to the router through the use of a management subnet and if using pfSense, setup a root and server certificate in the Cert. Manager within the System menu and add a root certificate to your web browser of your choice. Use a management subnet for any devices that have SSH access or a web interface and do not allow managers, sales, web developers, or any other non-IT departments access to the critical network infrastructure.

Update: I just hit “c” twice in my keyboard (ccode instead of code) even though I only typed “c” just once. Ugh… Maybe I just need a different keyboard that prevents double-types regardless of the operating system I’m using… (And yes, I’m using Arch Linux.)

IPv4 Subnetting Practice

If you understand computer networking and know how IPv4 subnetting works, here’s a zip file which contains a self-contained HTML file. Double-click in the HTML file and you can begin practicing.

ipv4subnet.zip

Have fun!