One place for hosting & domains

      How to Fix the 500 Internal Server Error in WordPress (10 Tips)


      Seeing a 500 internal server error where your website should be is enough to throw anyone into a panic. When your website goes down, you lose out on potential traffic and sales. If it’s offline for a while, it can also negatively impact your Search Engine Optimization (SEO) efforts.

      Fortunately, there are plenty of ways to go about fixing this error. Many of these solutions are fairly straightforward, and you don’t need a lot of technical know-how to start troubleshooting.

      In this guide, we’ll cover what the 500 internal server error in WordPress is and discuss some potential causes. Then we’ll give you 10 tips to help you get your website back in working order.

      1. Back up your website.
      2. Try reloading the page.
      3. Clear your browser cache.
      4. Access your error logs.
      5. Check for the “Error Establishing a Database Connection.”
      6. Look for permission errors.
      7. Increase your PHP memory limit.
      8. Check for problems with your .htaccess file.
      9. Look for coding or syntax errors in your CGI/Perl script.
      10. Ask your web host about potential server issues.

      Let’s get started!

      Dealing with the WordPress Internal Server Error?

      Avoid troubleshooting when you sign up for DreamPress. Our friendly WordPress experts are available 24/7 to help solve website problems — big or small.

      What Is the 500 Internal Server Error?

      The 500 internal server error is frustratingly nonspecific. When the error occurs, you usually don’t get many details about it. In fact, you might not receive any information at all.

      An example of a 500 internal server error screen.

      The 500 error is a generic issue that isn’t specific to WordPress. Chances are you’ve seen it before during your internet explorations. Despite the name, it doesn’t necessarily mean that something is wrong with your server. It could be an issue with your website or browser.

      If you do see this error on your site, you’ll want to get it fixed as quickly as possible. A 500 error can impact your SEO if allowed to linger. If your site is crawled while it’s offline, there’s a chance that Google may interpret the error as an issue with your website.

      This error can also hurt your User Experience (UX) and give visitors the impression that you’re unprofessional. Not only can a poor UX affect the way Google ranks your site, but it can cause you to lose customers as well. After all, you can’t do business if your site isn’t accessible.

      A wide variety of situations can result in the 500 error, making it a bit of a chore to sort out. Potential causes of the 500 internal server error in WordPress include:

      • Plugin compatibility issues
      • Exhausted PHP memory limit
      • Corrupted files
      • Coding or syntax errors

      The fact that the error message itself tends to be vague doesn’t help. Fortunately, you can solve many of these issues on your own with a bit of know-how.

      Variations on the 500 Internal Server Error

      Depending on your operating system, browser, and the cause of the error, there are variations in how it will appear. For example, if a database connection can’t be established, you might see something like this:

      An error establishing a database connection message.

      A plain white screen, sometimes referred to as the White Screen of Death (WSoD), can indicate a 500 internal server error.

      A blank browser window due to a 500 error.

      Also, many site owners have the option to customize their 500 error messages. So you might see this error in many different forms.

      How to Fix the 500 Internal Server Error in WordPress (10 Tips)

      Now that you’ve had an introduction to the 500 internal server error, it’s time to discuss how to resolve it. Let’s take a look at ten tips you can use to fix this issue in WordPress.

      1. Back up your website.

      Before tinkering under the hood, it’s always smart to make a backup of your website. If DreamHost hosts your site, you can take advantage of our one-click backup feature. You can also create a manual backup if you prefer.

      To make a complete backup, you’ll need to save copies of your WordPress files as well as your databases. You can back up your site’s files using a Secure File Transfer Protocol (SFTP) client such as FileZilla.

      Once you’re connected to your server, navigate to the WordPress files you want to save. These files include the WordPress core installation, plugins, themes, images, and more. To save the files, simply right-click on them and select Download.

      How to download WordPress files via SFTP.

      Now you’ll need to back up your database, which you can do by logging into phpMyAdmin. Select the database you want to download from the left-hand panel, and then click on the Export tab.

      You’ll then need to choose between a “Quick” or a “Custom” export. The Quick export will likely work just fine unless you need to manage more advanced options.

      Options for downloading a WordPress database using phpMyAdmin.

      Click on the Go button, and your download should start. Once your website is safely backed up, you can get to work on fixing that 500 error.

      2. Try reloading the page.

      Let’s start with the best-case scenario. Some situations that cause a 500 internal error clear up on their own within a few minutes. For example, if you’ve just made changes to a plugin or theme, or if your host is experiencing unusually heavy traffic, you may see a server error. If this is true in your case, you’re in luck, as a simple page reload should get things back to normal.

      Therefore, the first thing to try is simply waiting a minute or two, during which the error will hopefully resolve itself. Then you can try reloading the page by pressing F5 or (command + R if you’re using a Mac).

      3. Clear your browser cache.

      Another potential server error fix that’s quick and easy is clearing your browser cache. It’s possible the cache became corrupted, which would cause problems when attempting to access websites.

      First, you might check Down For Everyone Or Just Me. This will determine whether there’s a widespread problem or you’re the only one experiencing difficulties.

      Amazon.com’s status on Down for Everyone or Just Me.

      If you’re alone in your 500 error frustration, the problem may be your browser. Try accessing your site from a different browser. If an alternative works, it’s a sign that the issue is with your cache.

      In Google Chrome, you can clear your cache by pressing Ctrl + Shift + Delete. Alternatively, you can click on the three vertical dots in the top-right corner, followed by More tools > Clear browsing data.

      Options for clearing the browser cache in Chrome.

      Be sure to check the Cached images and files box. Then click on the Clear data button.

      In Firefox, you can clear the cache using the Ctrl + Shift + Delete keyboard shortcut. This will open the Clear Recent History window. In the Time range to clear drop-down menu, select Everything. Check the Cache box, and then click on OK.

      Options for clearing browser data in Firefox.

      In Safari, you can navigate to the History menu item and choose Clear History. Keep in mind that this will delete everything, including cookies and visited pages.

      How to clear the browser cache in Safari.

      Once you’ve cleared your browser cache, you can attempt to access your website again. If you’re still seeing the 500 internal server error, it’s time to move on to more involved fixes.

      4. Access your error logs.

      Your site’s error logs may provide insight into what’s causing the 500 error. Depending on your host, these logs may be cycled quite often, so you’ll want to take a look as soon as possible.

      You can check your error logs by accessing your site’s files via SFTP and looking for the /logs directory. Next, select the site that’s experiencing the error. You may see several directories at this point. You’ll want to check the one with the most recent date.

      Error and access log files accessed via FileZilla.

      You can view the log by downloading it and opening it with your preferred text editor. Hopefully, your error logs will provide you with some additional context for the 500 error.

      Another option is to enable the WordPress debug log. You can do this by connecting to your site via SFTP and opening your wp-config.php file. Within it, look for the following line:

      define('WP_DEBUG', false);

      Once you find it, replace it with the following:

      define( 'WP_DEBUG', true );
      
      define( 'WP_DEBUG_DISPLAY', false );
      
      define( 'WP_DEBUG_LOG', true );

      This will create a debug.log file, which you can find under the /wp-content/ directory. Just be sure to change the WP_DEBUG value back to “false” when you’re done troubleshooting.

      5. Check for the ‘Error Establishing a Database Connection.’

      If there’s been a problem establishing a database connection, not only will your site be offline for visitors, but you won’t be able to access the WordPress admin dashboard either. There are a few possible causes of this:

      • Incorrect database login credentials
      • A corrupted WordPress database
      • A corrupted WordPress installation file

      Let’s start with incorrect login credentials, as this is a common cause of the database connection error. If you’re a DreamHost user, you can find your database credentials in your panel. However, if you use a different host, you’ll likely follow a similar procedure.

      Navigate to MySQL Databases and find the one that corresponds to your website under the Database(s) on this server section. Here, you’ll find your database name under the Database heading. The username is listed under the Users Access column.

      Alt-text: Where to find your MySQL username in DreamPanel.

      To find the password, click on the username. On the next screen, scroll down and click on the Show button next to the password field.

      How to find your database password in DreamPanel.

      Next, you’ll compare these credentials to those in your wp-config.php file. You can access this file in your site’s main directory via SFTP. Once you have the file downloaded, open it and verify that the information under MySQL Settings matches what you found in your panel.

      Checking MySQL settings in the wpconfig.php file.

      Next, if your database is corrupted, you can quickly repair it through phpMyAdmin. Log in and click on your database in the left panel. Select all of the tables in the database, and then choose the Repair table option from the drop-down menu.

      Repairing a database in phpMyAdmin.

      Finally, let’s look at how to handle a corrupted WordPress installation file. Start by downloading a new copy of WordPress and unzipping the file. You’ll need to delete the wp-content folder and the wp-config-sample.php file.

      Deleting files from a new WordPress installation.

      Upload the rest of the files to your site via SFTP, overwriting any existing ones. You now have a brand new, uncorrupted WordPress installation. You’ll also want to clear your browser cache before checking your website again.

      6. Look for permission errors.

      If any of your files have permissions set incorrectly, you may see the 500 internal server error as a result. Again, you can check and change these permissions using SFTP.

      Right-click on any file and select File permissions to open a new dialogue window. In this window, you can check and, if necessary, set new permissions for the file.

      Checking and updating file permissions using FileZilla.

      Typically, you’ll want to set files to “644” and directories and executables to “755”. However, you may want to check with your host if you’re unsure about the correct values.

      7. Increase your PHP memory limit.

      Another reason you might see the 500 internal server error is if you’ve exceeded your server’s PHP memory limit. There are several ways to increase your limit, and they all involve using SFTP.

      Before you try increasing your memory limit, you may want to start by seeing what it’s currently set to. You can do this through the WordPress admin dashboard. Keep in mind that, with some variations of the 500 error, you won’t be able to access the dashboard. If that’s the case, you may have to skip this step.

      From your WordPress dashboard, navigate to Tools > Site Health. Click on Info at the top of the screen, and scroll down to the Server section. You should see your PHP memory limit there.

      How to check your WordPress site’s PHP memory limit.

      To increase the PHP memory limit, there are a few files you can edit. One is your .htaccess file, typically located in your site’s root directory. Open the file and add the following code:

      php_value memory_limit xxxM

      You can replace the “xxx” with your desired amount of memory. Usually, 256M is plenty.

      You can also increase your memory limit by editing your php.ini file. You should be able to find this file in your root directory. If not, you can go ahead and create one. Add or update its code to the following:

      memory_limit = xxxM

      Another option is to add in the following code at the top of your wp-config.php file:

      define('WP_MEMORY_LIMIT', 'xxxM');

      If this resolves the 500 error, your next task will be to figure out what is causing the memory limit exhaustion. It could be a problematic plugin or theme. You might consider reaching out to your host for help on finding the exact server diagnostics.

      8. Check for problems with your .htaccess file.

      Your .htaccess file is one of the core WordPress files. It contains rules for your server, so it could contribute to a 500 internal server error.

      If your .htaccess file has become corrupted, you’ll want to go ahead and create a fresh one. Start by logging into your site via SFTP and finding your .htaccess file. Rename the file to .htaccess_old.

      Renaming a file in FileZilla.

      Now, create a new .htaccess file in your text editor and paste in the following:

      # BEGIN WordPress
      
      RewriteEngine On
      
      RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
      
      RewriteBase /
      
      RewriteRule ^index.php$ - [L]
      
      RewriteCond %{REQUEST_FILENAME} !-f
      
      RewriteCond %{REQUEST_FILENAME} !-d
      
      RewriteRule . /index.php [L]
      
      # END WordPress

      Go ahead and upload your newly created .htaccess file. Then refresh your site in your browser, and check to see whether the error message is showing.

      9. Look for coding or syntax errors in your CGI/Perl script.

      If you’re running Common Gateway Interface (CGI) scripts, any coding errors you’ve made could result in a 500 error. To unearth potential issues with your CGI scripts, log into your site using Secure Shell Access (SSH).

      Once you’ve logged in, you can troubleshoot your CGI with this command:

      [server]$ ./cgi_name.cgi

      The terminal should return a general error message and the line number the culprit is located on. From there, you can work your coding magic!

      When working with CGI, there are a few best practices to keep in mind to avoid problems. First, it’s wise to use a plain text editor to ensure that you maintain ASCII format. When you upload scripts, you should also be able to select ASCII mode in your FTP client.

      Changing the transfer type option in FileZilla.

      Finally, if necessary, upload to the cgi-bin directory on your server. Then you can double-check your files’ permissions once you have them uploaded.

      10. Ask your web host about potential server issues.

      If all else fails, there may be a server issue, which only your host can confirm. Unfortunately, if your host’s server is experiencing a problem, you may have to wait out some website downtime.

      If you’re a DreamHost client, you can check the DreamHost Status page. This resource provides you with information on all of our services.

      The DreamHost status page.

      If you run into any problems while trying to repair the 500 internal server error, you can always reach out to our tech support team. They’re ready and waiting to lend you a hand! If you’ve followed the tips in this guide, you’ll have plenty of valuable information for the technician.

      Ready to Dive into Your Error Log?

      Whether you need help with file permission, identifying a hidden file, or dealing with a faulty plugin, we can help! Subscribe to our monthly digest so you never miss an article.

      Let’s Get Your WordPress Website Back on Track

      While having to sort out a 500 internal server error isn’t exactly fun, it’s also not as painful as you might imagine. With a little patience and the tips we’ve provided, you should be able to make some progress on getting your website back online.

      You can start small by refreshing your page and clearing your browser cache. Then you might want to move onto more involved fixes, such as increasing your PHP memory limit. If you’re not able to resolve the error on your own, DreamHost’s award-winning tech support is just a click away.

      When you do run into errors, it’s easier to get back up and running when you have a reliable hosting provider. DreamPress is fast, secure WordPress hosting with powerful features to help make your site a success!



      Source link

      Top 10 Tips for Protecting Yourself and Your Data


      How to Join

      This Tech Talk is free and open to everyone. Register on Eventbrite here to receive a link to join on Thursday, January 14, 2021, 11:00 a.m.–12:00 p.m. ET.

      About the Talk

      When most people hear about a hacked company in the news, they usually assume that it was some type of technical failing that led to this exploit. More often than not, this assumption is wrong, since the attacker targeted the most vulnerable and often-overlooked security measure: the people.

      What You’ll Learn

      • Social engineering techniques and how to protect yourself from them
      • How attackers actually gain access to systems
      • How to protect yourself, and by extension, your systems

      About the Presenter

      Mason Egger is currently a Developer Advocate at DigitalOcean, specializing in cloud infrastructure, distributed systems, and Python. Prior to his work at DigitalOcean, he was an SRE (Site Reliability Engineer), helping build and maintain a highly available hybrid multi-cloud PaaS. He is an avid programmer, speaker, educator, and writer/blogger. He is a maintainer of the DigitalOcean Terraform provider and contributes to random open source projects here and there. In his spare time, he enjoys reading, camping, kayaking, and exploring new places.

      To join the live Tech Talk, register here.



      Source link

      5 Tips to Write Better Conditionals in JavaScript


      When working with JavaScript, we deal a lot with conditionals, here are the 5 tips for you to write better / cleaner conditionals.

      1. Use Array.includes for Multiple Criteria

      Let’s take a look at the example below:

      // condition
      function test(fruit) {
        if (fruit == 'apple' || fruit == 'strawberry') {
          console.log('red');
        }
      }
      

      At first glance, the above example looks good. However, what if we get more red fruits, say cherry and cranberries? Are we going to extend the statement with more || ?

      We can rewrite the conditional above by using Array.includes (Array.includes)

      function test(fruit) {
        // extract conditions to array
        const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
        if (redFruits.includes(fruit)) {
          console.log('red');
        }
      }
      

      We extract the red fruits (conditions) to an array. By doing this, the code looks tidier.

      2. Less Nesting, Return Early

      Let’s expand the previous example to include two more conditions:

      • if no fruit provided, throw error
      • accept and print the fruit quantity if exceed 10.
      function test(fruit, quantity) {
        const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
        // condition 1: fruit must has value
        if (fruit) {
          // condition 2: must be red
          if (redFruits.includes(fruit)) {
            console.log('red');
      
            // condition 3: must be big quantity
            if (quantity > 10) {
              console.log('big quantity');
            }
          }
        } else {
          throw new Error('No fruit!');
        }
      }
      
      // test results
      test(null); // error: No fruits
      test('apple'); // print: red
      test('apple', 20); // print: red, big quantity
      

      Look at the code above, we have:

      • 1 if/else statement that filter out invalid condition
      • 3 levels of nested if statement (condition 1, 2 & 3)

      A general rule I personally follow is return early when invalid conditions found.

      /_ return early when invalid conditions found _/
      
      function test(fruit, quantity) {
        const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
        // condition 1: throw error early
        if (!fruit) throw new Error('No fruit!');
      
        // condition 2: must be red
        if (redFruits.includes(fruit)) {
          console.log('red');
      
          // condition 3: must be big quantity
          if (quantity > 10) {
            console.log('big quantity');
          }
        }
      }
      

      By doing this, we have one less level of nested statement. This coding style is good especially when you have long if statement (imagine you need to scroll to the very bottom to know there is an else statement, not cool).

      We can further reduce the nesting if, by inverting the conditions & return early. Look at condition 2 below to see how we do it:

      /_ return early when invalid conditions found _/
      
      function test(fruit, quantity) {
        const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
      
        if (!fruit) throw new Error('No fruit!'); // condition 1: throw error early
        if (!redFruits.includes(fruit)) return; // condition 2: stop when fruit is not red
      
        console.log('red');
      
        // condition 3: must be big quantity
        if (quantity > 10) {
          console.log('big quantity');
        }
      }
      

      By inverting the conditions of condition 2, our code is now free of a nested statement. This technique is useful when we have long logic to go and we want to stop further process when a condition is not fulfilled.

      However, that’s no hard rule for doing this. Ask yourself, is this version (without nesting) better / more readable than the previous one (condition 2 with nested)?

      For me, I would just leave it as the previous version (condition 2 with nested). It is because:

      • the code is short and straight forward, it is clearer with nested if
      • inverting condition may incur more thinking process (increase cognitive load)

      Therefore, always aims for Less Nesting and Return Early but don’t overdo it. There is an article & StackOverflow discussion that talks further on this topic if you interested:

      3. Use Default Function Parameters and Destructuring

      I guess the code below might look familiar to you, we always need to check for null / undefined value and assign default value when working with JavaScript:

      function test(fruit, quantity) {
        if (!fruit) return;
        const q = quantity || 1; // if quantity not provided, default to one
      
        console.log(`We have ${q} ${fruit}!`);
      }
      
      //test results
      test('banana'); // We have 1 banana!
      test('apple', 2); // We have 2 apple!
      

      In fact, we can eliminate the variable q by assigning default function parameters.

      function test(fruit, quantity = 1) { // if quantity not provided, default to one
        if (!fruit) return;
        console.log(`We have ${quantity} ${fruit}!`);
      }
      
      //test results
      test('banana'); // We have 1 banana!
      test('apple', 2); // We have 2 apple!
      

      Much easier & intuitive isn’t it? Please note that each parameter can has it own default function parameter. For example, we can assign default value to fruit too: function test(fruit="unknown", quantity = 1).

      What if our fruit is an object? Can we assign default parameter?

      function test(fruit) { 
        // printing fruit name if value provided
        if (fruit && fruit.name)  {
          console.log (fruit.name);
        } else {
          console.log('unknown');
        }
      }
      
      //test results
      test(undefined); // unknown
      test({ }); // unknown
      test({ name: 'apple', color: 'red' }); // apple
      

      Look at the example above, we want to print the fruit name if it’s available or we will print unknown. We can avoid the conditional fruit && fruit.name checking with default function parameter & destructing.

      // destructing - get name property only
      // assign default empty object {}
      function test({name} = {}) {
        console.log (name || 'unknown');
      }
      
      //test results
      test(undefined); // unknown
      test({ }); // unknown
      test({ name: 'apple', color: 'red' }); // apple
      

      Since we only need property name from fruit, we can destructure the parameter using {name}, then we can use name as variable in our code instead of fruit.name.

      We also assign empty object {} as default value. If we do not do so, you will get error when executing the line test(undefined)Cannot destructure property name of 'undefined' or 'null'. because there is no name property in undefined.

      If you don’t mind using 3rd party libraries, there are a few ways to cut down null checking:

      • use Lodash get function
      • use Facebook open source’s idx library (with Babeljs)

      Here is an example of using Lodash:

      // Include lodash library, you will get _
      function test(fruit) {
        console.log(__.get(fruit, 'name', 'unknown'); // get property name, if not available, assign default value 'unknown'
      }
      
      //test results
      test(undefined); // unknown
      test({ }); // unknown
      test({ name: 'apple', color: 'red' }); // apple
      

      You may run the demo code here. Besides, if you are a fan of Functional Programming (FP), you may opt to use Lodash fp, the functional version of Lodash (method changed to get or getOr).

      4. Favor Map / Object Literal than Switch Statement

      Let’s look at the example below, we want to print fruits based on color:

      function test(color) {
        // use switch case to find fruits in color
        switch (color) {
          case 'red':
            return ['apple', 'strawberry'];
          case 'yellow':
            return ['banana', 'pineapple'];
          case 'purple':
            return ['grape', 'plum'];
          default:
            return [];
        }
      }
      
      //test results
      test(null); // []
      test('yellow'); // ['banana', 'pineapple']
      

      The above code seems nothing wrong, but I find it quite verbose. The same result can be achieve with object literal with cleaner syntax:

      // use object literal to find fruits in color
        const fruitColor = {
          red: ['apple', 'strawberry'],
          yellow: ['banana', 'pineapple'],
          purple: ['grape', 'plum']
        };
      
      function test(color) {
        return fruitColor[color] || [];
      }
      

      Alternatively, you may use Map to achieve the same result:

      // use Map to find fruits in color
        const fruitColor = new Map()
          .set('red', ['apple', 'strawberry'])
          .set('yellow', ['banana', 'pineapple'])
          .set('purple', ['grape', 'plum']);
      
      function test(color) {
        return fruitColor.get(color) || [];
      }
      

      Map is the object type available since ES2015, allow you to store key value pair.

      Should we ban the usage of switch statement? Do not limit yourself to that. Personally, I use object literal whenever possible, but I wouldn’t set hard rule to block that, use whichever make sense for your scenario.

      Todd Motto has an article that dig deeper on switch statement vs object literal, you may read here.

      TL;DR; Refactor the syntax

      For the example above, we can actually refactor our code to achieve the same result with Array.filter .

      
       const fruits = [
          { name: 'apple', color: 'red' }, 
          { name: 'strawberry', color: 'red' }, 
          { name: 'banana', color: 'yellow' }, 
          { name: 'pineapple', color: 'yellow' }, 
          { name: 'grape', color: 'purple' }, 
          { name: 'plum', color: 'purple' }
      ];
      
      function test(color) {
        // use Array filter to find fruits in color
      
        return fruits.filter(f => f.color == color);
      }
      

      There’s always more than 1 way to achieve the same result. We have shown 4 with the same example. Coding is fun!

      5. Use Array.every & Array.some for All / Partial Criteria

      This last tip is more about utilizing new (but not so new) Javascript Array function to reduce the lines of code. Look at the code below, we want to check if all fruits are in red color:

      const fruits = [
          { name: 'apple', color: 'red' },
          { name: 'banana', color: 'yellow' },
          { name: 'grape', color: 'purple' }
        ];
      
      function test() {
        let isAllRed = true;
      
        // condition: all fruits must be red
        for (let f of fruits) {
          if (!isAllRed) break;
          isAllRed = (f.color == 'red');
        }
      
        console.log(isAllRed); // false
      }
      

      The code is so long! We can reduce the number of lines with Array.every:

      const fruits = [
          { name: 'apple', color: 'red' },
          { name: 'banana', color: 'yellow' },
          { name: 'grape', color: 'purple' }
        ];
      
      function test() {
        // condition: short way, all fruits must be red
        const isAllRed = fruits.every(f => f.color == 'red');
      
        console.log(isAllRed); // false
      }
      

      Much cleaner now right? In a similar way, if we want to test if any of the fruit is red, we can use Array.some to achieve it in one line.

      const fruits = [
          { name: 'apple', color: 'red' },
          { name: 'banana', color: 'yellow' },
          { name: 'grape', color: 'purple' }
      ];
      
      function test() {
        // condition: if any fruit is red
        const isAnyRed = fruits.some(f => f.color == 'red');
      
        console.log(isAnyRed); // true
      }
      

      Summary

      Let’s produce more readable code together. I hope you learn something new in this article.

      That’s all. Happy coding!



      Source link