technology
How To: Use PHP to Change a Bluehost Email Account Password
This is a PHP script I wrote that allows you to incorporate an email password update option into your own webpage styling. Normally, with Bluehost (and FastDomain and HostMonster), your users can only change their email account password by either having the admin login to their cpanel and changing it for them, or by accessing the Bluehost provided webmail interface. Neither are very inviting solutions, especially in a professional environment.
The script works by accessing the shadow file associated with the email account’s domain name. It looks for the username whose password is being changed in the shadow file and, if found, compares the password stored in the shadow file with the password that the user enters as their current password. If those passwords match, it then updates the shadow file with the users’ new password. The password is stored in the shadow file as a Base64 encoded salted MD5 hash which is generated using either the PHP crypt function (if available) or the openssl command line.
This script will work out of the box, however, I recommend using it with the current visual theme of your website otherwise you’re defeating the purpose. The hidden input field named “domain” may be edited so that users only have to enter the name portion (ie: joesnuffy) of their email address without the domain portion. If left un-edited, your users will be required to enter in the domain portion of their email address along with the name portion (ie: joesnuffy@linuxr0ckz.com).
This script will work with Bluehost, FastDomain, HostMonster (all operated by Bluehost) and I’m guessing it will also work with any other host that uses cpanel (unverified).
<?php
$message = "";
$found = $valid = false;
if (isset($_POST['username']) && $_POST['username'] != "") {
$domain_pos = strpos($_POST['username'], "@");
if ($domain_pos === false) {
$username = $_POST['username'];
$domain = $_POST['domain'];
} else {
$username = substr($_POST['username'], 0, $domain_pos);
$domain = substr($_POST['username'], $domain_pos + 1);
}
$current_password = $_POST['current_password'];
$new_password1 = $_POST['new_password1'];
$new_password2 = $_POST['new_password2'];
$root = $_SERVER['DOCUMENT_ROOT'];
$path_elements = explode('/', $root);
$root = "/{$path_elements[1]}/{$path_elements[2]}"; // for bluehost, extracts homedir ex: /homeN/blueuser may work with other hosts?
$shadow_file = "$root/etc/$domain/shadow";
// check if the shadow file exists. if not, either an invalid
// domain was entered or this may not be a bluehost account...?
if (file_exists($shadow_file)) {
// compare the new passwords entered to ensure they match.
if ($new_password1 == $new_password2) {
if (trim($new_password1) != "") {
// get the contents of the shadow file.
$shadow = file_get_contents($shadow_file);
$lines = explode("\n", $shadow);
// go through each line of shadow file, looking for username entered.
for ($i = 0; $i < count($lines); $i++) {
$elements = explode(":", $lines[$i]);
// found the user...
if ($elements[0] == $username) {
$found = true;
$passwd = explode("$", $elements[1]);
$salt = $passwd[2]; // get the salt currently used
// crypt the "Current Password" entered by user. Can use either builtin
// php crypt function or command line openssl command.
if (CRYPT_MD5 == 1) { // indicates whether or not the crypt command supports MD5.
$current = crypt($current_password, '$1$'.$salt.'$');
} else {
$current = trim(`openssl passwd -1 -salt "$salt" "$current_password"`);
}
// check if the current password entered by the user
// matches the password in the shadow file.
$valid = ($current == $elements[1]);
if ($valid) {
// if they match then crypt the new password using the same salt
// and modify the line in the shadow file with the new hashed password
if (CRYPT_MD5 == 1) {
$new = crypt($new_password1, '$1$'.$salt.'$');
} else {
$new = trim(`openssl passwd -1 -salt "$salt" "$new_password1"`);
}
$elements[1] = $new;
$lines[$i] = implode(":", $elements);
}
break;
}
}
if (!$found) {
$message = "The username you entered is not valid.";
} else if (!$valid) {
$message = "The password you entered is not valid.";
} else {
// write the new contents of the shadow back to the shadow file.
$shadow = implode("\n", $lines);
file_put_contents($shadow_file, $shadow);
$message = 'Your password has been updated.';
}
} else {
$message = "Your password cannot be blank.";
}
} else {
$message = "Both new passwords must match.";
}
} else {
$message = "The domain you entered is not valid.";
}
}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Change Password</title>
</head>
<body>
<?php
if ($message != "") {
$color = $found && $valid ? "green" : "red";
echo "<span style=\"color:$color;\">$message</span>";
}
?>
<form action="" method="post">
<input type="hidden" name="domain" value="somebluehostdomain.com" />
<table>
<tbody>
<tr>
<td><label for="username">Username</label></td>
<td><input name="username" id="username" type="text" /></td>
</tr>
<tr>
<td><label for="current_password">Current Password</label></td>
<td><input name="current_password" id="current_password" type="password" /></td>
</tr>
<tr>
<td><label for="new_password1">New Password</label></td>
<td><input name="new_password1" id="new_password1" type="password" /></td>
</tr>
<tr>
<td><label for="new_password2">New Password</label></td>
<td><input name="new_password2" id="new_password2" type="password" /></td>
</tr>
<tr>
<td colspan="2" style="text-align:center;">
<input type="submit" value="Update Password" />
</td>
</tr>
</tbody>
</table>
</form>
</body>
</html>
Windows 7 as a Wi-Fi Access Point
Ever needed a wireless router but didn’t have one handy? Ever use an ad-hoc wireless network with Internet Connection Sharing to get other devices connected quickly? What if you have say an Android phone with no cell network data connection but really need to connect it to the Internet but don’t have a wireless router handy (Android won’t connect to an ad-hoc network without rooting the device)? Here’s how to setup Windows 7 to act as a Wi-Fi access point (aka infrastructure) for you and anyone else you want to allow to connect. Note: This doesn’t work on Windows 7 Starter Edition as Internet Connection Sharing is not enabled.
- Open an elevated command prompt.
- Execute the following command, replacing <some_ssid> with an ssid of your choosing and <some_passphrase> with a wpa2 compatible passphrase. If either contain spaces, enclose that portion of the command in quotes:
netsh wlan set hostednetwork mode=allow <some_ssid> <some_passphrase> persistent - Enable Internet Connection Sharing. See Using ICS (Internet Connection Sharing)
- Execute the following command, again using an elevated command prompt:
netsh wlan start hostednetwork - All done. Your other Wi-Fi devices should now see your wireless network and be able to connect to it.
Note: Using this method to connect an Android device, I could not get T-Mobile Wi-Fi Calling to connect to their service. I’m guessing the double-NAT would’ve caused an issue, although I have been able to connect through a double-NAT before.
Vonage Mobile on Android – How to find your SIP information
If you have Vonage Mobile on your Android based smartphone you know that you’re able to make free calls over WiFi. I’m currently in a different country using a satellite Internet connection and the Vonage Mobile app is having trouble staying connected to the WiFi here, so I’m using 3CXPhone setup with the SIP server information for Vonage Mobile which is working much better (I tried using fring, but people I called couldn’t hear me although I could hear them). Here are two methods on how to find your SIP information for Vonage Mobile so that you can use other devices or other Android apps with SIP capabilities.
Using ADB
- Install ADB (http://developer.android.com/guide/developing/tools/adb.html)
- Turn on “USB Debugging” on your Android.
On the device, to go the home screen, press MENU, select Applications > Development, then enable USB debugging. - Connect your phone to your computer.
- Open a command prompt (Win+R, type “cmd”, press Enter)
- Type in “adb root”
- Type in “adb shell”
- Type in “cat /data/data/com.vonage.andrd/shared_prefs/VonageSettings.xml”
- Your SIP username is where you see SipPrincipal in the xml file. Your SIP password is where you see SipPassword, and the SIP server (or proxy server) is where you see SipDomain.
Using a terminal emulator on your Android (like Better Terminal Emulator) for rooted phones ONLY:
- Type in “su”
- Type in “cat /data/data/com.vonage.andrd/shared_prefs/VonageSettings.xml”
- Your SIP username is where you see SipPrincipal in the xml file. Your SIP password is where you see SipPassword, and the SIP server (or proxy server) is where you see SipDomain.
|
Vonage Mobile for Android |
3CXPhone for Android (VoIP) |
fring |
Better Terminal Emulator Pro |
|
|
|
|
|
Install exFAT FUSE Module for Ubuntu with Read/Write Support
http://code.google.com/p/exfat/
sudo apt-get install subversion scons libfuse-dev gcc
cd ~
svn co http://exfat.googlecode.com/svn/trunk/ exfat-read-only
cd exfat-read-only
scons
sudo scons install
cd ..
rm –rf exfat-read-only
sudo mkdir [mountpoint]
sudo mount –t exfat-fuse [device_path] [mountpoint]
Replace [device_path] with the device path to your exfat partition, for example: /dev/sdb1. Replace [mountpoint] with the path to your mount point, for example: /media/disk
Accessing an IMAP account using SSL (OpenSSL on Gmail)
C:\>openssl s_client -crlf -connect imap.gmail.com:993
CONNECTED(00000003)
depth=1 /C=US/O=Google Inc/CN=Google Internet Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=imap.gmail.com
i:/C=US/O=Google Inc/CN=Google Internet Authority
1 s:/C=US/O=Google Inc/CN=Google Internet Authority
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDWzCCAsSgAwIBAgIKYgnCCAADAAAJ5DANBgkqhkiG9w0BAQUFADBGMQswCQYD
VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu
dGVybmV0IEF1dGhvcml0eTAeFw0wOTA3MTcxNzEzNDFaFw0xMDA3MTcxNzIzNDFa
MGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N
b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRcwFQYDVQQDEw5pbWFw
LmdtYWlsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA+O0vc2pslfjk
pbxnBF4iznJMrP9Qi3fHjKqA3P2RynTcbnZfGEGMKcPeXHT4IOH6XUnf+4Jw+z7I
KiMtjX8IVGo7DeXec/ZREasEZnpMGisxN7+qk7Ho6HyaglQTAFIQJP99UFJkHO9x
dGDy5d2j9senPad1BqtyaIRGkJpHizUCAwEAAaOCASwwggEoMB0GA1UdDgQWBBT0
WHOeLKf4+VNADzHzGh+AEV+6fjAfBgNVHSMEGDAWgBS/wDDr9UMRPme6npH7/Gra
42sSJDBbBgNVHR8EVDBSMFCgTqBMhkpodHRwOi8vd3d3LmdzdGF0aWMuY29tL0dv
b2dsZUludGVybmV0QXV0aG9yaXR5L0dvb2dsZUludGVybmV0QXV0aG9yaXR5LmNy
bDBmBggrBgEFBQcBAQRaMFgwVgYIKwYBBQUHMAKGSmh0dHA6Ly93d3cuZ3N0YXRp
Yy5jb20vR29vZ2xlSW50ZXJuZXRBdXRob3JpdHkvR29vZ2xlSW50ZXJuZXRBdXRo
b3JpdHkuY3J0MCEGCSsGAQQBgjcUAgQUHhIAVwBlAGIAUwBlAHIAdgBlAHIwDQYJ
KoZIhvcNAQEFBQADgYEAXLvdKJJ6ivWAi29p4pPo4cirMEYnRlpNOmPVAW4QYcSq
lEZhm4cQdyitFo9cxiwNgbBjJk8O+oiOhnueT44RXotEE7j3KnNyPRRZg0OCagGC
4G71fFA11P1L0fSd/7k52/DbZQBea3tJgkseoGL50UVvnJm+LZOovIGxoQzipJk=
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=imap.gmail.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority
---
No client certificate CA names sent
---
SSL handshake has read 1704 bytes and written 300 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
Session-ID: 059F9016BB7EF76FC1080A02368D4812EF5619D9176C176412A0A8F786C2E71C
Session-ID-ctx:
Master-Key: EFE3B0BFEAE372829EA6B9B306BEB5BE2F5BBE5D325CF9F01940BB25C8353A16
08DA3A85DC0D4581DD482F2C7B9759EB
Key-Arg : None
Start Time: 1264807587
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
* OK Gimap ready for requests from 71.231.242.11 31if8927301pzk.40
A01 LOGIN username password
* CAPABILITY IMAP4rev1 UNSELECT LITERAL+ IDLE NAMESPACE QUOTA ID XLIST CHILDREN
X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
A01 OK username authenticated (Success)
A02 SELECT INBOX
* FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)]
* OK [UIDVALIDITY 2]
* 2636 EXISTS
* 0 RECENT
* OK [UIDNEXT 15043]
A02 OK [READ-WRITE] INBOX selected. (Success)
A04 IDLE
+ idling
DONE
A04 OK IDLE terminated (Success)
A05 LOGOUT
* BYE LOGOUT Requested
A05 OK 73 good day (Success)
read:errno=0
Convert NRG to ISO using DD
Earlier this week I was on a mission to convert an NRG image file to an ISO image file. I didn’t want to download a program that someone had already written like nrg2iso and instead preferred to use something like the linux dd command or write my own program that could do. I started digging into the NRG file format and found that it’s actually an IFF file. The documentation on how Nero implemented the IFF format into their NRG files isn’t very clear at all and is incorrect so with the information I was able to find I had to reverse engineer the format myself. Here’s how to convert an NRG image to ISO using the dd command (if you’re on windows you can install Cygwin to gain access to the dd command).
An NRG image is a CD-ROM image followed by Nero’s “footer” about the image, it’s cue sheets, cd text, and so on. The last twelve bytes of an NRG image file contain the NER5 header and an offset to the first CUE sheet of the image. Even though this offset is just a pointer to the first CUE sheet, you can use it determine the actual length of the image. Here’s what to do with dd.
- First, take the filesize of the NRG file and subtract 12 from it. Here, my NRG is 964,984,988 bytes. So I’m going to use 964984976 for the skip parameter of the dd command like so:
dd ibs=1 skip=964984976 if=Image.nrg of=footer.dat
- That will give you a 12 byte file named footer.dat. Open footer.dat in your favorite HEX Editor (I use UltraEdit-32).
- The first four bytes you should see is NER5. The next eight bytes is a 64-bit number that points to the first CUE sheet. Open Calculator. Set it for Scientific view (Programmer view in Windows 7, maybe Windows Vista too?). Change to Hex mode and type in exactly what you see for those eight bytes. My Hex heditor shows 00 00 00 00 39 84 80 00. So in Calculator I type in 39848000 (you can drop all leading zeros since this is a little-endian number).
- Now switch back to Decimal mode. The Hex number you typed in will change to a Decimal number (964984832 in my case), this is the offset at which the first CUE sheet exists in the NRG image. It also happens to be (in most cases) the length of the cd image. Since the cd image is the first thing in the NRG file, all you have to do now is extract the contents of the image into your ISO file.
- Divide your decimal offset number by 2048. For me, 964984832 / 2048 = 471184. That’s how many blocks (a block being 2048 bytes for us) we’re going to copy from the NRG file to the ISO file. Now just run the DD command:
dd ibs=2048 count=471184 if=Image.nrg of=Image.iso
That’s it.. now mount your ISO image to a virtual cd/dvd/bd drive like Virtual CloneDrive (or burn it) and make sure it works before deleting your NRG file.
Yahoo! Widgets, Google Gadgets, and Dashboard Widgets
I just finished my first project as an independent contractor writing software programs. A company, PredictWallStreet, Inc., approached me after seeing a Yahoo! Widget I had written and wanted me to write a Yahoo! Widget for them. They also wanted the same Widget as a Google Desktop Gadget and an Apple Dashboard Widget. Knowing nothing about the Google Desktop engine or the Apple Dashboard engine I accepted the offer, signing my life away to get these projects done within the specified amount of time.
First came the Yahoo! Widget. I took a look at the webpage PredictWallStreet had setup for the Widgets’ use and quickly thought it might be a little more difficult than I had initially imagined. The online version of the program provided by PredictWallStreet, to my surprise, was programmed by a local company, Omniture, Inc. Omniture does some really weird stuff with their html forms and it took me a minute to figure out exactly what they do. At any rate, like I had always thought, it’s ALWAYS possible to trick a web server into thinking you’re coming from somewhere you’re not… essentially emulating the behavior of a real web browser when in reality your program is only acting as a front end to a webpage. I finished the Yahoo! Widget in just a couple days.
Next came the Google Desktop Gadget. I figured it would be a fairly simple process to convert a Yahoo! Widget into a Google Desktop Gadget… until I started digging in to Google’s API. Boy was I wrong. Google does everything 100% different than Yahoo. I basically had to completely rewrite the entire Widget for the Google Desktop engine. After getting the hang of how Google does things, it once again only took a couple days to complete the Google Desktop Gadget.
And finally, the Apple Dashboard Widget. It took me a few days to get Mac OS X 10.4.6 running on my x86 PC. I could get it installed and running just fine, except for the mouse would shoot to the top left corner of the screen about every second. I could not develop on a system that was behaving like this, how annoying. I finally traced the problem back to the Bluetooth transceiver I was using for my mouse and keyboard. For some reason that was causing the problem. As soon as I removed the Bluetooth transceiver and used a wireless USB mouse I was good to go. This time I really thought that Apple would be more like Yahoo and that it would be relatively simple to convert the Yahoo widget to an Apple Widget… Wrong again! The Apple Dashboard engine was completely different then both Google Gadgets AND Yahoo! Widgets. I had to completely rewrite it again to work with the Apple Dashboard. I was impressed, however, at Apple’s way of doing things. Their widget engine is designed to be completely to W3C HTML standards. You can develop the entire widget in HTML, JavaScript, and CSS all the while testing, and debugging using Safari (or Firefox, I recommend Safari since that is what the Dashboard is based off of). Google and Yahoo have a completely non-standard implementation of their engines.
All of this is possible because of the XMLHttpRequest. With the Yahoo! Widget I used the built-in URL object, but after completing the Google and Apple versions, I realized I should have done the Yahoo Widget with XMLHttpRequest as well. Oh well, it works. Despite Apple’s impressive implementation following industry standards, I prefer the Yahoo! Widgets. It is much easier to code and debug using Yahoo! Widgets and their documentation is very complete and easy to navigate. However, once getting used to how to debug with Apple Dashboard Widgets it really isn’t bad at all, and I just want to stress again how impressed I am with Apple’s implementation. The only thing I don’t like about Apple Dashboard Widgets is that they can only be displayed on the Dock and not on the Desktop like with Yahoo! Widgets and Google Gadgets (on Windows, Google Gadgets used the same Dock that Apple does on Mac OS X). Google Gadgets’ dumb side bar is extremely annoying on Windows. If you try to get rid of the sidebar it always puts a toolbar on Windows taskbar… that’s even more annoying. I did a registry hack and removed the Google Gadget toolbar CLSID to permanently keep it from appearing (I do the same thing with the MS Office Language bar).
Anyway, I don’t know the point of this blog other than to just ramble about these three very different implementations of the same thing. If anyone would like something written be sure to contact me. I work with any of the .Net languages (mostly C#, VB.Net, and ASP.Net), PHP, MySQL, MS SQL, Yahoo! Widgets, Google Gadgets, Apple Dashboard Widgets, and others (forget Java, PERL, RoR and other crappy languages like that (although I can do RoR too)).
Tanner
Recent Posts
- How To: Use PHP to Change a Bluehost Email Account Password
- How to: Merge Multiple Video Files Into One Using ffmpeg
- Windows 7 as a Wi-Fi Access Point
- Grammar, Spelling and Numbers
- Bulk Convert DOCX to DOC
- Collage Generator
- Identify This Cipher
- Interesting Error from Win 7
- Binary Clock – My First Android App
- Vonage Mobile on Android – How to find your SIP information
- Crest Prime
- The Travelling Salesman Problem
- Install exFAT FUSE Module for Ubuntu with Read/Write Support
- Accessing an IMAP account using SSL (OpenSSL on Gmail)
- Color Wheel
- Bulk Convert XLSX to XLS
- Convert NRG to ISO using DD
- Afghanistan: CRC for the contractor
- Personality Types
- Iraq: CRC for the contractor
- Yahoo! Widgets, Google Gadgets, and Dashboard Widgets



