Feb 12
21
I’ve been working on my first scanner. I decided to build the “new standard scanner”. The step by step guide to building it can be found here, but as it is fresh in my mind I want to throw out a couple of notes.
First, you only have to be pretty accurate in your measurements and cuts. For the most part the tolerance is quite large… which is good for me.
Second, this is a 90 degree scanner. That is, the book is held open at 90 degrees. Between 100 and 110 degrees is going to be a little better. The thing is that at 90 you are very close to ideal partly because your book bindings won’t get messed up from being opened too far. However, if you make it closer to 100 degrees you will get most of the same benefit while also removing a small amount of “reflection” where the camera picks up the page across from what it’s shooting. It’s just a suggestion, but I’ll be building my second version to 100 degrees or maybe even up to 110 degrees. What would be awesome is if you angle was adjustable. And now that I think about it that might not be that hard and would be worth looking in to.
Third, do pre-drill holes before you screw them, especially on pieces of wood that you just spent a long time cutting! The screw can split your wood if you’re not careful.
references:
http://www.diybookscanner.org/
http://www.diybookscanner.org/forum/viewtopic.php?f=1&t=333
As a super final last note I have to mention that while writing this post I went to the main diybookscanner.org page and then clicked on forum. When I did I was redirected to some other site… I think it was either an “ru” or an “nu” and had ff in it somewhere, I think. I was unable to reproduce it, and nothing ever loaded on the page, but it somehow caused me to be logged out of most sites. I’ve never had any problems visiting the diy site before, but I thought I’d mention it just in case.
I’m working on an iPhone / iPad app that needs to be able to authenticate itself to the server from which it requests data. The users of the app will have an account with the website so they will already have a username / password. There is no SSL functionality, so I needed a way to authenticate over plaintext without giving away the password or even the hash of it.
Let’s talk about what the webserver does in relation to storing the password. It doesn’t actually store the password. It stores a hashed value where the actual password was combined with a salt (random string of a descent length) and that combined string was hashed using SHA256. The result is stored as the “password” for the user and the salt used to compute the hash is also stored for that user. When the user logs in the password they send (using ssl, so it is encrypted between the user and server) is combined with the stored salt and hashed. If the result is the same as the stored hash then the user is authenticated, otherwise they are not.
Here’s a little helper class for doing the Hash. It’s server side and .net specific.
#region HashingLogic
public class Hash
{
public Hash() { }
public enum HashType : int
{
MD5,
SHA1,
SHA256,
SHA512
}
public static string GetHash(string text, HashType hashType)
{
HashAlgorithm _algorithm;
switch (hashType)
{
case HashType.MD5:
_algorithm = MD5.Create();
break;
case HashType.SHA1:
_algorithm = SHA1.Create();
break;
case HashType.SHA256:
_algorithm = SHA256.Create();
break;
case HashType.SHA512:
_algorithm = SHA512.Create();
break;
default:
throw new ArgumentException(“Invalid hash type”, “hashType”);
}
byte[] bytes = Encoding.Unicode.GetBytes(text);
byte[] hash = _algorithm.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format(“{0:x2}”, x);
}
return hashString;
}
public static bool CheckHash(string original, string hashString, HashType hashType)
{
string originalHash = GetHash(original, hashType);
return (originalHash == hashString);
}
}
#endregion
And here’s the webserver checking the Hash. It should be pretty easy to see how to store it as well when a user sets their password in the first place.
// ran a query that returned the hashed password and salt for the user in question
// note: password is the value sent by the user trying to log in
string the_hashed_password = dt.Rows[0]["vcHashedPass"].ToString().Trim();
string the_salt = dt.Rows[0]["vcPassSalt"].ToString().Trim();
string the_salted_password = password.Trim() + the_salt;
string hashedvalue = Hash.GetHash(the_salted_password, Hash.HashType.SHA256);
if (hashedvalue == the_hashed_password)
loginSuccessful = true;
Now that we have the background, I can talk about what really screwed with me. I was trying to implement part of this on the iOS side. , but I was getting a different value back for my hash. I used a Hash library for iOS from this site. It was easy to use. Just copy the files to your project and import the .h into whatever file you need to do hashing. Before hashing an NSString you must first convert it to an NSData. But this conversion requires you to specify the encoding. To use it in conjunction with the .Net helper class above you have to choose the right encoding or it will has to the wrong value. Code first, then discussion.
NSString *usernameex = [keychainwrapper objectForKey:(id)kSecAttrAccount];
NSString *passwordex = [keychainwrapper objectForKey:(id)kSecValueData];
// I’m hardcoding the salt for this example, now we need to talk to the server to see if it will let us log in with it
NSString *retrievedSalt = [NSString stringWithFormat:@"b3b5c979-3438-4f56-aa1a-1d85bda78b7e"];
NSString *saltedpassword = [NSString stringWithFormat:@"%@%@", passwordex, retrievedSalt];
// Webserver thinks that hashed(password+salt) =
// 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1 — looking for
// but this library was returning various results… here’s one
// ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e — getting
HashValue *hashvalue;
//NSUTF16StringEncoding 762ce0d893b64032f11562e4ee0be3f4ed08ca6b801ab892d319af3942ca788c
NSData* datasaltedpassword0a=[saltedpassword dataUsingEncoding:NSUTF16StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0a];
ASLog(@”hashedvalue0a – %@”, hashvalue.description); // password – whatever you entered
NSData* datasaltedpassword0b=[saltedpassword dataUsingEncoding:NSUTF16BigEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0b];
ASLog(@”hashedvalue0b – %@”, hashvalue.description); // password – whatever you entered
NSData* datasaltedpassword0c=[saltedpassword dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0c];
ASLog(@”hashedvalue0c – %@”, hashvalue.description); // password – whatever you entered
NSData* datasaltedpassword0d=[saltedpassword dataUsingEncoding:NSUTF32StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0d];
ASLog(@”hashedvalue0d – %@”, hashvalue.description); // password – whatever you entered
NSData* datasaltedpassword0e=[saltedpassword dataUsingEncoding:NSUTF32BigEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0e];
ASLog(@”hashedvalue0e – %@”, hashvalue.description); // password – whatever you entered
NSData* datasaltedpassword0f=[saltedpassword dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0f];
ASLog(@”hashedvalue0f – %@”, hashvalue.description); // password – whatever you entered
//NSUTF8StringEncoding
NSData* datasaltedpassword1=[saltedpassword dataUsingEncoding:NSUTF8StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword1];
ASLog(@”hashedvalue1 – %@”, hashvalue.description); // password – whatever you entered
//[NSString defaultCStringEncoding]
NSData* datasaltedpassword2=[saltedpassword dataUsingEncoding:[NSString defaultCStringEncoding]];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword2];
ASLog(@”hashedvalue2 – %@”, hashvalue.description); // password – whatever you entered
//NSUnicodeStringEncoding allowLossyConversion:NO
NSData* datasaltedpassword3=[saltedpassword dataUsingEncoding:NSUnicodeStringEncoding allowLossyConversion:NO];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword3];
ASLog(@”hashedvalue3 – %@”, hashvalue.description); // password – whatever you entered
//NSWindowsCP1252StringEncoding
NSData* datasaltedpassword4=[saltedpassword dataUsingEncoding:NSWindowsCP1252StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword4];
ASLog(@”hashedvalue4 – %@”, hashvalue.description); // password – whatever you entered
//NSMacOSRomanStringEncoding
NSData* datasaltedpassword5=[saltedpassword dataUsingEncoding:NSMacOSRomanStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword5];
ASLog(@”hashedvalue5 – %@”, hashvalue.description); // password – whatever you entered
ASLog(@”targetvalue – 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1″, hashvalue.description); // password – whatever you entered
And the output:
2012-02-05 16:13:38.077 [11082:560f] LoginViewController.m:121 -[LoginViewController workOfDoLogin] password – ocelot
2012-02-05 16:13:38.078 [11082:560f] LoginViewController.m:140 -[LoginViewController workOfDoLogin] salt – b3b5c979-3438-4f56-aa1a-1d85bda78b7e
2012-02-05 16:13:38.078 [11082:560f] LoginViewController.m:144 -[LoginViewController workOfDoLogin] saltedpassword – ocelotb3b5c979-3438-4f56-aa1a-1d85bda78b7e
2012-02-05 16:13:38.080 [11082:560f] LoginViewController.m:152 -[LoginViewController workOfDoLogin] hashedvalue0a – 762ce0d893b64032f11562e4ee0be3f4ed08ca6b801ab892d319af3942ca788c
2012-02-05 16:13:38.080 [11082:560f] LoginViewController.m:156 -[LoginViewController workOfDoLogin] hashedvalue0b – df7e828a1df0664ff42756960ab7f63e83f0504437c59286e217df32147d8815
2012-02-05 16:13:38.081 [11082:560f] LoginViewController.m:160 -[LoginViewController workOfDoLogin] hashedvalue0c – 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1
2012-02-05 16:13:38.082 [11082:560f] LoginViewController.m:164 -[LoginViewController workOfDoLogin] hashedvalue0d – 4276b8d7ff791492f537379bf7353095d8ce40c717f15dc242f2847b376b88de
2012-02-05 16:13:38.083 [11082:560f] LoginViewController.m:168 -[LoginViewController workOfDoLogin] hashedvalue0e – 45838174fdf6cb95b7ed6bdbd7409f065c75f12958e58ae84ec5d28235b6cf0e
2012-02-05 16:13:38.083 [11082:560f] LoginViewController.m:172 -[LoginViewController workOfDoLogin] hashedvalue0f – 492adfab98090cf9319684aa707d368a2689495480a59ffd7a9b2a514ea9362d
2012-02-05 16:13:38.084 [11082:560f] LoginViewController.m:178 -[LoginViewController workOfDoLogin] hashedvalue1 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e
2012-02-05 16:13:38.085 [11082:560f] LoginViewController.m:183 -[LoginViewController workOfDoLogin] hashedvalue2 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e
2012-02-05 16:13:38.086 [11082:560f] LoginViewController.m:188 -[LoginViewController workOfDoLogin] hashedvalue3 – 762ce0d893b64032f11562e4ee0be3f4ed08ca6b801ab892d319af3942ca788c
2012-02-05 16:13:38.086 [11082:560f] LoginViewController.m:193 -[LoginViewController workOfDoLogin] hashedvalue4 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e
2012-02-05 16:13:38.087 [11082:560f] LoginViewController.m:198 -[LoginViewController workOfDoLogin] hashedvalue5 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e
2012-02-05 16:13:38.088 [11082:560f] LoginViewController.m:201 -[LoginViewController workOfDoLogin] targetvalue – 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1
The right Encoding to use on the iOS side was “NSUTF16LittleEndianStringEncoding”. I had to do all of those tests to finally find which one matched the values being produced on the web side (.Net)… so just keep in mind that if your getting two different hashes then you might need to use a different Encoding during the conversion from String to Byte / Data in order to make them sync up.
If you are working on an iOS app and have the need for the user the enter input then you usually use a textfield or textview. I was working on a login screen and had a very annoying experience where the keyboard wouldn’t go away after I had finished entering my text. What was especially annoying was that I had encountered it before and had simply forgotten how to resolve it. So I’m writing this up for myself or anyone else who needs the info.
All you have to do is make sure that your view has ‘User Interaction Enabled’ checked under the ‘Attributes Inspector’. Then add the following block of code to your view’s implementation. You can see that I have two textFields called txtUsername and txtPassword. You’ll want to change them to match the names of all the text fields on your form (you don’t know which one is actually the first responder at the time, but from what I’ve read it doesn’t hurt to resign if you are not it anyway). So that’s it.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[self.txtPassword resignFirstResponder];
[self.txtUserName resignFirstResponder];
}
}
Here’s another place that discusses it in a bit more detail.
I’ll also mention that some people use a hidden button the size of the view. Then they tie that button to a “hideKeyboard” method. That solution is also discussed in that thread. I found a better explanation of it a Sams Publishing teach yourself Iphone Development book, but the discussion on that thread will suffice. For my own reference it is on page 179-182. It also discusses how to release the keyboard when the “Done” button is pressed. You will probably want to implement BOTH.
Dec 11
28
I’m currently reviewing an existing system written in vb6 that management at the company I work for has finally decided to get behind porting it. Their plan is to port it to Visual Studio (VB.net) as that is what they are comfortable with. I understand this desire, but I’m also hesitant to jump right in and do so because they are also looking for “better ways to do things” during the transition. This particular system is very “rules driven” and we have a massive amount of code dedicated to supporting these rules. In my opinion this is just screaming for Prolog to be a part of the solution, and since I have some say in the matter I’ll be as neck deep in prolog over the next couple of months. I’ll be trying to get a proof of concept in place before the conversion gets underway so I can prove its value. Either that, or I might just prove that it won’t do the job I want it to and I will be able to dive into the rewrite as previously planned without hesitation or hinderance.
While I can’t tell you what the project is I can tell you that in just one of my fact databases I expect to have well over 1/2 million facts. The facts are relatively static so that’s good. The facts will be queried upon often over 1million times per day and it should be able to handle that without breaking a sweat as this is only about 5% of the total volume we expect to see.
So, that being said, I’m working on compiling a list of Prolog references (websites mainly) that will help me progress as quickly and painlessly as possible. If you have any suggestions for books I’d also love to hear them and will likely be adding them to the post or as seperate posts as I go.
So, here come my links on into topics:
http://boklm.eu/prolog/page_0.html
SWI-Prolog
A short Introduction to Prolog
A Short Tutorial On Prolog
Introduction to Prolog for Mathematicians
iProlog Programmer’s Manual
Prolog Tutorials
A Concise Introduction to Prolog
Dec 11
4
True in sports, business, and life in general:
IF you can keep your head when all about you
Are losing theirs and blaming it on you,
If you can trust yourself when all men doubt you,
But make allowance for their doubting too;
If you can wait and not be tired by waiting,
Or being lied about, don’t deal in lies,
Or being hated, don’t give way to hating,
And yet don’t look too good, nor talk too wise:If you can dream – and not make dreams your master;
If you can think – and not make thoughts your aim;
If you can meet with Triumph and Disaster
And treat those two impostors just the same;
If you can bear to hear the truth you’ve spoken
Twisted by knaves to make a trap for fools,
Or watch the things you gave your life to, broken,
And stoop and build ‘em up with worn-out tools:If you can make one heap of all your winnings
And risk it on one turn of pitch-and-toss,
And lose, and start again at your beginnings
And never breathe a word about your loss;
If you can force your heart and nerve and sinew
To serve your turn long after they are gone,
And so hold on when there is nothing in you
Except the Will which says to them: ‘Hold on!’If you can talk with crowds and keep your virtue,
‘ Or walk with Kings – nor lose the common touch,
if neither foes nor loving friends can hurt you,
If all men count with you, but none too much;
If you can fill the unforgiving minute
With sixty seconds’ worth of distance run,
Yours is the Earth and everything that’s in it,
And – which is more – you’ll be a Man, my son!
I got my iRobot looj “gutter robot” yesterday. I’ve been really looking forward to getting one for a while now and finally got it ordered late last week. Not bad for a delivery time! I think I ordered it on Thursday and received it tuesday with free shipping.
Include in the box were two batteries, a charging device, the robot itself including the remote, a beltclip, and two augers. It came in a nice tool case (like you might get with a cordless drill or other cordless power tools) that will allow me to store it neatly out of the way when I’m not using it so I’m liking that too.
I’m writing this because I read various reviews and some were good while others were not so much. I wanted to write it while it was fresh in my head (I just used it about 2 hours ago) because I remember thinking while I was using it that “man, I didn’t realize…” so I figured I’d give a heads up to anyone else looking to spend their money.
First, I want to say that I think this will make cleaning my gutters much safer. I hate getting up and down off the ladder. The way my house was built leaves me with what amounts to second story gutters and I just hate climbing up and down over and over again to clean them. The other option I had was to climb up on the roof and just crawl along the entire roof line on my hands and knees scraping out the gutters by hand. This required me to be way to close the edge contantl and made me really nervous on the steeper graded parts of the roof (which
also happened to be over the highest part of the roof directly over my stone patio). With this looj I was able to find one place that I could climb up, place the looj, and then let it do its thing to clean pretty much the entire gutter area on the back of my house.
It worked pretty well. The gutters got clean enough. I can honestly say that if I was paying a person to clean my gutters. I would require them to have done a better job as there was still some debris left when all was said and done, but probably 95% of it was able to be cleared by the looj. Keep in mind this is a rookie “driver” and I was in a bit of a hurry as I had to get back to work so it might have done even better if I knew what to do, but it worked pretty well regardless.
You do have to pay attention while you use it. You can’t just set it and forget it. For example, I did encounter a couple of times where the looj rolled over. Basically the auger got stuck in some mess that it wasn’t able to break up and so the robot itself just started spinning. It was amusing in a way, but not so much in that I had to go rescue it. It seemed that several times it just quit responding for a few seconds, but then it when right back to working. I don’t know if it got to the edge of the range of the remote or what… in any case it did not make the device unusable, just a little quirky.
I did have one downspout for which the auger never was able to clear out the opening. I had to climb up and clear that one downspout myself. This is still significantly less work than I normally have to do.
This first use was in gutters full of dry leaves, some acorns, and very few pine needles. It hadn’t rained for a couple of weeks so the leaves weren’t wet and the gutters weren’t wet. It took a few passes to get everything out. I plan to use it again soon after a rain (it will rain tonight and I don’t have time to do the front before the rain will be here) so I’ll be able to see which way works best. The second test will includes lots of pine needles so we’ll see how it actually handles them!
I do not think that this device will make my gutter cleaning faster. Working the looj back and forth to get it through heavier jams may actually make it take longer, but I do think it will make it much safer and require less physical exhertion on my behalf.
Cleaning the device for storage was super easy. I just turned on hose and rinsed the looj off. It was pretty “cruddy”, but nothing major and cleaned up quickly and easily.
If they make another model then I would recommend making it a little heavier (maybe 50%) and make the tread motors a little tougher.
I plan to do another review once I get a chance to try this on my gutter that has a pineneedle problem just to report on how that goes. For now though, I’m pretty darn satisfied with the value I received for the money I spent.
The below table is a description of iphone icons and ipad icons, what they’re sizes and should be, and what their standardized names are. This information is all over, but the a thorough and yet concise version (and what i based the below on) can be found here.
| Name | Size (pixels) | Platform |
| Icon.png | 57 x 57 | Universial application icon |
| Icon-settings.png | 29 x 29 | Universial application icon for settings area. Alternative name: Icon-Small.png |
| Icon~ipad.png | 72 x 72 | iPad application icon. Alternative name: Icon-72.png Add some smaller (iPad doc: 64×64, other optional 32×32, 24×24, 16×16) custom icons to your project. See comments. |
| Icon-spot~ipad.png | 50 x 50 | iPad icon for spotlight search. Alternative name: Icon-Small-50.png iPhone OS trims 1 pixel from each side and adds a drop shadow. The actual size is 48×48 pixels. |
| iTunesArtwork.png | 512 x 512 | Universial application icon for iTunes App Store. Uploaded separately to iTunes. It’s included in the app bundle too, file name: iTunesArtwork. In an iPad application iPhone OS uses this image to generate the large (320×320) document icon if it is not supplied otherwise. |
| Default.png | 320 (w) x 480 (h) | iPhone/iPod 2, 3 portrait launch image |
| Default@2x.png | 640 (w) x 960 (h) | iPhone 4 hi-res portrait launch image |
| Default~ipad.png | 768 (w) x 1004 (h) | iPad. Specifies the default portrait launch image. This image is used if a more specific image is not available. Use full size template (768×1024) to design this launch image. The 20 pixels height statusbar is on by default and occupies the top of the screen, aka the 1004 rows vs. 1024. |
| Optional icons and images: | ||
| Icon@2x.png | 114 x 114 | iPhone 4 hi-res application icon |
| Icon-settings@2x.png | 58 x 58 | iPhone 4 hi-res application icon for settings/search area |
| Icon-doc.png | 22 (w) x 29 (h) | Universial document icon |
| Icon-doc@2x.png | 44 (w) x 58 (h) | iPhone 4 hi-res document icon |
| Icon-doc~ipad.png | 64 x 64 | iPad document icon (small) |
| Icon-doc320~ipad.png | 320 x 320 | iPad document icon (large) |
| Background-xxx.png | 320 (w) x 480 (h) 640 (w) x 960 (h) 768 (w) x 1024 (h) |
iPhone/iPod Touch 2, 3 background image, iPhone 4 background image, full size iPad background image, full size. For most projects the status bar is hidden, so use full screen size by default. |
| Default-PortraitUpsideDown~ipad.png | 768 (w) x 1004 (h) | iPad. Specifies an upside-down portrait version of the launch image. The height of this image should be 1004 pixels and the width should be 768. This file takes precedence over the Default-Portrait.png image file for this specific orientation. |
| Default-LandscapeLeft~ipad.png | 1024 (w) x 748 (h) | iPad. Specifies a left-oriented landscape version of the launch image. The height of this image should be 748 pixels and the width should be 1024. This file takes precedence over the Default-Landscape.png image file for this specific orientation. |
| Default-LandscapeRight~ipad.png | 1024 (w) x 748 (h) | iPad. Specifies a right-oriented landscape version of the launch image. The height of this image should be 748 pixels and the width should be 1024. This file takes precedence over the Default-Landscape.png image file for this specific orientation. |
| Default-Portrait~ipad.png | 768 (w) x 1004 (h) | iPad. Specifies the generic portrait version of the launch image. The height of this image should be 1004 pixels and the width should be 768. This image is used for right side-up portrait orientations and takes precedence over the Default~ipad.png image file. If a Default-PortraitUpsideDown.png image file is not specified, this file is also used for upside-down portrait orientations as well. |
| Default-Landscape~ipad.png | 1024 (w) x 748 (h) | iPad. Specifies the generic landscape version of the launch image. The height of this image should be 748 pixels and the width should be 1024. If a Default-LandscapeLet.png or Default-LandscapeRight.png image file is not specified, this image is used instead. This image takes precedence over the Default.png image file. |
I have recently been working on a new iOS app for the iPhone and I ran into a couple of issues. I don’t really have time to go over them all in this post, but I did want to document one of them because I hear it can be a big deal as far as getting your app approved by Apple. The issue is that of making sure you handle things gracefully if the user’s phone is unable to connect to the internet and they try to do something that does require a connection.
The way I decided to handle it was to use the reachability collection provided by apple. I downloaded the reachability sample from Apple and then copied and imported the 4 files from the “classes” directory into my project.
Then I added the “SystemConfiguration.framework” to my project.
Now I have all of the prereqs for my solution. The next thing I did was I created a NetworkReachabilityTest class with NSObject as its base class. I added a single method called “isNetworkReachableWithAlert” that returned a bool and included one parameter. The parameter specified whether it should automatically pop up an alert box in case of a lack of network connectivity.
I chose to do it this way (as a dumb small class) so I didn’t have to copy the code for this method into every page. Plus it gives me the flexibility to easily reuse it in future projects. So now, before I do something that requires network connectivity I instantiate an instance of this class, I do the check, and if the connection is there I do the work. If the connection is not there I can bail out instead.
Here’s the code (some of this code was included in the example and some was found here around post 29 or 30:
-(BOOL) isNetworkReachableWithAlert:(BOOL)bshowalert
{
Reachability *r = [Reachability reachabilityWithHostName:@"www.signandtrade.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
{
if (bshowalert)
{
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@”No Internet Connection” message:@”An internet connection via WiFi or cellular network is required for this portion of the app to work.” delegate:self cancelButtonTitle:@”Ok” otherButtonTitles:nil];
[myAlert show];
[myAlert release];
}
return NO;
}
return YES;
}
That’s in the implementation file of my simple class and it is basically the only thing there! And it does everything we need.
And here it is in use:
NetworkReachabilityTest *nrt = [[NetworkReachabilityTest alloc] init];
if ([nrt isNetworkReachableWithAlert:YES])
{
// logic that requires or includes web activity here
}
[nrt release];
Hope that helps. Hope it makes sense. Better ideas or improvements on it are welcome, I just wanted to give someone a simple example of something that I know works along with the steps I took to make it work.
I have an Mac OSx machine on which I have virtualbox installed. My most often used virtual client machine runs Windows XP. Almost everything works great, but I was having a lot of issues getting printing to work. I finally got everything figure out though and figured I’d write it up real quick. So here’s what I did.
The first thing I would recommend doing if you have a setup like mine is to find the driver for the printer that you need to print to. Why? Because the apple software that I point you to below will install a driver by default that technically works, but that makes everything you print come out super small. Actually, as I’m writing this is occurs to me that it may be because apple assumes an HP printer, but mine is an Epson. So maybe the default installed by the program provided by Apple will work “out of the box” for an HP printer… But I would still go ahead and get the correct driver for your printer first.
Then once you have the driver on the client then do the following (found this at virtualbox.org forum and quoted from here):
1) Shutdown the VirtualBox machine
2) Under Mac OS X
a) System Preferences, Print & Fax, Check “Share this printer on the network”
b) System Preferences, Sharing, Check “Printer Sharing” and Check the printer
3) VirtualBox machine, Network:
a) if only one adapter selected and it is attached as NAT [this is the default], then add Second adapter attached as Host-only Adapter, Name: vboxnet0
b) if the adapter is attached as Bridged Adapter, then do nothing (you have a reason to be Bridged?)
4) Start up the Vbox machine – let it adjust to added Network Adapter
a) Download and install from Apple “Bonjour Print Services for Windows” http://support.apple.com/kb/DL999
b) start Bonjour Printer Wizard and follow the menus
That wizard will allow you to print from the client using the printer on the host MacOSx machine. But that wasn’t it for me because Apple defaulted to an HP driver which caused the pages to print all tiny on my Epson. It was an easy fix though. I just had to go back and run the brand specific printer driver install (or manually change the printer driver for the printer added by the apple wizard) so that it would use the brand specific driver instead of the Apple default.
Aug 11
28