{"id":1116,"date":"2011-02-06T14:41:09","date_gmt":"2011-02-06T20:41:09","guid":{"rendered":"http:\/\/thepizzy.net\/blog\/?p=1116"},"modified":"2014-05-22T21:15:35","modified_gmt":"2014-05-23T02:15:35","slug":"how-to-connect-to-sql-through-windows-authenticated-odbc-in-php","status":"publish","type":"post","link":"https:\/\/thepizzy.net\/blog\/2011\/02\/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php\/","title":{"rendered":"How to Connect to SQL through Windows Authenticated ODBC in PHP"},"content":{"rendered":"<p>For about the last year, I&#8217;ve been creating a CMS (content management system) named Jada, for the automatic management and maintenance of my company&#8217;s eCommerce site, on the Yahoo! Store platform. The software imports the entire store automatically, runs a series of cleanup processes with about a dozen different criteria, saves the changes it has made, exports the modified pages, and makes them available to download from Jada&#8217;s interface. This automation cuts the need for about 3-4 people doing a weeks&#8217; worth of work, and does it all automatically in 10-30 minutes. The one thing it doesn&#8217;t do is the one cleanup process that takes the longest, and requires the most human thought: comparing every product&#8217;s available options on the site, and checking them against actual inventory in the order management software.<\/p>\n<p>Until now.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1125\" data-permalink=\"https:\/\/thepizzy.net\/blog\/2011\/02\/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php\/attachment\/8787717937219497341\/\" data-orig-file=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?fit=256%2C256&amp;ssl=1\" data-orig-size=\"256,256\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ODBC Connection\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?fit=256%2C256&amp;ssl=1\" class=\"alignright size-thumbnail wp-image-1125\" src=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341-150x150.png?resize=150%2C150\" alt=\"ODBC Connection\" width=\"150\" height=\"150\" srcset=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?resize=36%2C36&amp;ssl=1 36w, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?resize=115%2C115&amp;ssl=1 115w, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?w=256&amp;ssl=1 256w\" sizes=\"auto, (max-width: 150px) 100vw, 150px\" \/>Our current order management software runs as a MS Access front-end to a MSSQL 2005 server backend through an ODBC DSN connection. This connection has been limited to MS Access and MS Excel application\/queries, and thus, was the limiting factor to writing this most-complex cleanup process into Jada. The most difficult part in my development was finding an understandable article describing how to make an ODBC call, and then actually get the data back, in the same simple manner that one makes a MySQL query. The real issue has been <strong>once the connection is closed, the result cannot be accessed<\/strong>. I had to find that out the hardway, via <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms811006.aspx\" target=\"_blank\">Microsoft&#8217;s convoluted documentation on using ODBC<\/a>.<\/p>\n<p>Here&#8217;s the code I&#8217;ve used to make the ODBC connection in PHP (unfortunately my blog&#8217;s template can&#8217;t handle actual code right now):<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1119\" data-permalink=\"https:\/\/thepizzy.net\/blog\/2011\/02\/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php\/2011-02-06_1313-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png?fit=630%2C786&amp;ssl=1\" data-orig-size=\"630,786\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"function odbcQuery()\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png?fit=580%2C724&amp;ssl=1\" class=\"aligncenter size-full wp-image-1119\" title=\"function odbcQuery()\" src=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png?resize=580%2C724\" alt=\"\" width=\"580\" height=\"724\" srcset=\"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png?w=630&amp;ssl=1 630w, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png?resize=240%2C300&amp;ssl=1 240w, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/2011-02-06_13131.png?resize=120%2C150&amp;ssl=1 120w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<h1>Code Breakdown<\/h1>\n<p>We&#8217;ll start creating a function that makes an ODBC connection, passes it an SQL query, then parses the data into a table\/array and return the array.<\/p>\n<h2>Function call<\/h2>\n<pre>function odbcQuery($sql, $attempt=\"\") {<\/pre>\n<p>When we call the function, we&#8217;ll provide the SQL Query we want executed, and an optional description of what we&#8217;re trying to do with the query. In this way, if it errors, an semantic error will be displayed along with the technical one to help locate the code easily.<\/p>\n<h2>Database Connection<\/h2>\n<pre>\/\/ Establish an odbc connection with the database\r\n$link = odbc_connect(\"My_DSN_Name\", \"\", \"\");<\/pre>\n<p>When running <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/function.odbc-connect.php\" target=\"_blank\">odbc_connect()<\/a><\/strong> it takes 3 parameters:<\/p>\n<ul>\n<li>the DSN; Server,Port; or Server\/SQLInstance<\/li>\n<li>username<\/li>\n<li>password<\/li>\n<\/ul>\n<p>When connecting using Windows Authentication &amp; a DSN (as this example is about), there are some caveats and things to remember:<\/p>\n<ol>\n<li>On the web server, the User running the Web Service process needs to be a User with permission to access the SQL Server.\n<ol>\n<li>In my case, the user running the web server is <strong>SYSTEM<\/strong>, and so the user trying to access the SQL server is &#8220;<strong>DOMAIN\\COMPUTERNAME$<\/strong>&#8220;.<\/li>\n<li>There is no password for a SYSTEM account, and so on the SQL Server needs to have a user created named &#8220;<strong>DOMAIN\\COMPUTERNAME$<\/strong>&#8220;.<\/li>\n<li>Due to some security concerns, I&#8217;ve decided to give the account read-only access to the database I want to access. You&#8217;ll need to consult your own IT Administrator or security advisor for your security concerns.<\/li>\n<\/ol>\n<\/li>\n<li>In the odbc_connect() statement, you then only need the name of the DSN (which I assume has already been configured on the Web Server you&#8217;re using) , followed by two null-quotes: &#8220;&#8221;.<\/li>\n<\/ol>\n<p>This creates an active link via ODBC to the SQL Server&#8230;supposedly<\/p>\n<h2>Database Connection Checking &amp; Error Handling<\/h2>\n<pre>if (!$link) {\r\n\tdie('Could not connect: '.odbc_error().': '.odbc_errormsg());\r\n} else {<\/pre>\n<p>Next, we check the link . If it just flat-out doesn&#8217;t exist, then we kill the program, throw an error message that will read: &#8220;Could not connect: &lt;;insert odbc error code&gt;;: &lt;;insert odbc error text&gt;;&#8221;. Otherwise, we move on&#8230;<\/p>\n<h2>Sending the SQL Query &amp; Checking Response<\/h2>\n<pre>$data = odbc_exec($link, $sql);\r\nif($data === false) {\r\n\techo \"ODBC Query: \".$sql.\"\r\n\r\n\";\r\n\tdie(\"ODBC Query failed:  \".$attempt.\"\r\nError: \".odbc_error());\r\n} else {<\/pre>\n<p>Now that we have a valid link to the database, we&#8217;ll send a request for <strong>data<\/strong> using the <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/function.odbc-exec.php\" target=\"_blank\">odbc_exec()<\/a><\/strong> function. This function sends the connection resource (<strong>$link<\/strong>) and the SQL Query we want run (<strong>$sql<\/strong>). It will return a &#8220;ODBC result identifier&#8221; or <em><strong>false<\/strong><\/em>.<\/p>\n<p>Since a result identifier could, I assume, be the number 0 (zero) I want to ensure that <strong>$data<\/strong> is actually <strong><em>false<\/em><\/strong> and not just zero. That&#8217;s where the triple === comes in. When doing conditional statements, using == will convert the data being compared into a true\/false value, where <em>zero or nothing<\/em> = <strong><em>false<\/em><\/strong> and <em>anything else<\/em> = <strong><em>true<\/em><\/strong>. When you use === you test for an actual boolean value, meaning <em>anything including zero<\/em> = <strong><em>true<\/em><\/strong> and <strong><em>false = false<\/em><\/strong>.<\/p>\n<p>If the query failed, and resulted in a <strong><em>false<\/em><\/strong> result, we&#8217;ll display an error message: &#8220;ODBC Query: &lt;;insert actual SQL Query&gt;; \/\/ ODBC Query failed: &lt;;insert query description&gt;; \/\/ Error: &lt;;insert ODBC error code&gt;;&#8221;. Otherwise, we&#8217;ll move on&#8230;<\/p>\n<h2>Parsing the Query Results &#8211; Column Headers<\/h2>\n<pre>\/\/ Initialization\r\n$row = $fields = $records = $result = array(); \t\r\n\r\n\/\/ Get the result's column names\r\n$count = odbc_num_fields($data);\r\nfor($x=1;$x&lt;=$count;$x++) {\r\n\t$fields[] = odbc_field_name($data, $x);\r\n}<\/pre>\n<p>We start off by initializing all the variables we&#8217;re going to use in the next bit of code, to make sure they&#8217;re empty.<\/p>\n<p>Then we&#8217;ll run <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/function.odbc-num-fields.php\" target=\"_blank\">odbc_num_fields()<\/a><\/strong> over the <strong>$data<\/strong> to get the number of columns we need to iterate through. For columns, the counting starts at 1, so the for-loop starts at 1.<\/p>\n<p>Iterate through each column name and add it to an array, called <strong>$fields<\/strong>:<\/p>\n<pre>Array (\r\n\t[0] =&gt; field_name_1\r\n\t[1] =&gt; field_name_2\r\n\t[2] =&gt; field_name_3\r\n)<\/pre>\n<h2>Parsing the Query Results &#8211; Records<\/h2>\n<pre>\/\/ Get the result's data: array[record#][column#] = value\r\n$count = odbc_num_rows($data);\r\nfor($x=0;$x&lt;$count;$x++) {\r\n\todbc_fetch_into($data, $row, $x);\r\n\tarray_push($records,$row);\r\n}<\/pre>\n<p>Then we run <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/function.odbc-num-rows.php\" target=\"_blank\">odbc_num_rows()<\/a><\/strong> over the $data to get the number of rows we need to iterate through. For rows, the counting starts at 0, so the for-loop starts at 0.<\/p>\n<p>Iterate through each record row and insert it to a temporary array <strong>$row<\/strong> using <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/function.odbc-fetch-into.php\" target=\"_blank\">odbc_fetch_into()<\/a><\/strong>. Then take <strong>$row<\/strong> and put it into an array of records, <strong>$records<\/strong> giving you something like this:<\/p>\n<pre>Array (\r\n\t[0] =&gt;; Array (\r\n\t\t[0] =&gt;; record_1_column_1\r\n\t\t[1] =&gt;; record_1_column_2\r\n\t\t[2] =&gt;; record_1_column_3\r\n\t)\r\n\t[1] =&gt;; Array (\r\n\t\t[0] =&gt;; record_2_column_1\r\n \t\t[1] =&gt;; record_2_column_2\r\n \t\t[2] =&gt;; record_2_column_3\r\n  \t)\r\n\t[2] =&gt;; Array (\r\n \t\t[0] =&gt;; record_3_column_1\r\n \t\t[1] =&gt;; record_3_column_2\r\n \t\t[2] =&gt;; record_3_column_3\r\n  \t)\r\n )<\/pre>\n<h2>Making the data useable<\/h2>\n<p>Now that we&#8217;ve got two tables\/arrays of data &#8211; the field\/column names, and each record&#8217;s array of data &#8211; it&#8217;s time to make it usable in a format that we can consistently expect to be returned. There are two ways to do this. We can create an array listind every record as an array with column_name keys and values<\/p>\n<pre>\/\/ Return data in the format: array[record_id][column_name] = value\r\nforeach($records as $rid =&gt;; $record) {\r\n\tforeach($fields as $key =&gt;; $name) {\r\n\t\t$result[$rid][$name] = $record[$key];\r\n\t}\r\n}<\/pre>\n<p>or we can list every column as an array of record id&#8217;s as keys and values.<\/p>\n<pre>\/\/ Return the data in the format: array[column_name][record_id] = value\r\nforeach($fields as $key =&gt;; $name) {\r\n\tforeach($records as $record) {\r\n\t\t$result[$name][] = $record[$key];\r\n\t}\r\n}<\/pre>\n<p>Personally I find the first option to be more consistent with my results when calling a 2-dimensional result from MySQL queries, so it is the one I have gone with in my example at the start of the post, and in this description.<\/p>\n<p>The <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/control-structures.foreach.php\" target=\"_blank\">foreach()<\/a><\/strong> statements describe a compilation of a <strong>$result<\/strong> array in this manner:<\/p>\n<ol>\n<li>For each item in the <strong>$records<\/strong> array, store the record_id as <strong>$rid<\/strong>, and the record array as <strong>$record<\/strong>.<\/li>\n<li>Then for each item in the <strong>$fields<\/strong> array, store its cardinality as <strong>$key<\/strong> and it&#8217;s value\/name as <strong>$name<\/strong>.<\/li>\n<li>Then compile an array, iterating through each of the fields, storing this <strong>$record<\/strong>&#8216;s associated cardinality <strong>$key<\/strong>&#8216;s value into the <strong>$result<\/strong> array&#8217;s storage for this record&#8217;s id (<strong>$rid<\/strong>) under the appropriate field name.<\/li>\n<\/ol>\n<p>It&#8217;s a lot easier to grasp than it sounds. Basically, take array from the Query Results &#8211; Records section, and replace the # with the column name in each: [#] =&gt;; record_y_column_x, but store it as a different array, called <strong>$results<\/strong>. The resulting array would look something like this:<\/p>\n<pre>Array (\r\n\t[0] =&gt;; Array (\r\n\t\t[column1] =&gt;; record_1_column_1_data\r\n\t\t[column2] =&gt;; record_1_column_2_data\r\n\t\t[column3] =&gt;; record_1_column_3_data\r\n\t)\r\n\t[1] =&gt;; Array (\r\n\t\t[column1] =&gt;; record_2_column_1_data\r\n \t\t[column2] =&gt;; record_2_column_2_data\r\n \t\t[column3] =&gt;; record_2_column_3_data\r\n  \t)\r\n\t[2] =&gt;; Array (\r\n \t\t[column1] =&gt;; record_3_column_1_data\r\n \t\t[column2] =&gt;; record_3_column_2_data\r\n \t\t[column3] =&gt;; record_3_column_3_data\r\n  \t)\r\n )<\/pre>\n<h2>Close the connection, Return the result<\/h2>\n<pre>\t\todbc_close($link);\r\n\t\treturn $result;\r\n\t}\r\n}<\/pre>\n<p>Now that we&#8217;ve stored the data we need from the volatile <strong>$data<\/strong> variable returned from the SQL Query into <strong>$result<\/strong>, we can close the connection to <strong>$link<\/strong> using <strong><a href=\"http:\/\/us3.php.net\/manual\/en\/function.odbc-close.php\" target=\"_blank\">odbc_close()<\/a><\/strong>, and then return <strong>$result<\/strong> for the program to do with it what it will.<\/p>\n<h1>Conclusion<\/h1>\n<p>This is just an example code that explains one way of many to extract a variable 1-2 dimension array of data from your SQL Query, using a Windows-Authenticated ODBC DSN connection. There are many other methods to do this, as well as security fixes, data scrubbing, and other modifications that one would probably want to do.<\/p>\n<p>This is the first function I&#8217;ve written in any language to access an SQL Server via ODBC. This is also a function that has worked in tests, but that I have not yet put into production. I encourage you to take this bit of explanation and massage it into something that fits your needs in the code that you&#8217;re writing, and don&#8217;t rely on what I&#8217;ve got here as a written-in-stone example of good production-level code. This sample will change many times before I actually implement it.<\/p>\n<p>Happy Hacking!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you use MSSQL over ODBC, connecting w\/ PHP is simply a DOMAIN\\WEBSERVER acct on the MSSQL server &#038; the DSN in PHP&#8217;s odbc_connect()<\/p>\n","protected":false},"author":1,"featured_media":1125,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[506,25,11,3],"tags":[832,824,825,833,823,827,152,831,292,826,828,829,830],"class_list":["post-1116","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","category-programming","category-projects","category-tech","tag-how-to-connect-to-sql-server-in-php-with-odbc","tag-microsoft-odbc","tag-microsoft-sql-server","tag-mssql","tag-odbc","tag-odbc-connection","tag-php","tag-php-odbc-connection","tag-sql","tag-sql-server-odbc-connection","tag-windows-authenticated-odbc","tag-windows-authenticated-odbc-connection","tag-windows-odbc-connection"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341.png?fit=256%2C256&ssl=1","jetpack_likes_enabled":false,"jetpack_shortlink":"https:\/\/wp.me\/prOO4-i0","jetpack-related-posts":[{"id":73,"url":"https:\/\/thepizzy.net\/blog\/2006\/09\/oracle-and-tsnlocalnet\/","url_meta":{"origin":1116,"position":0},"title":"[[Oracle]] and tsnlocal.net","author":"[[Neo]]","date":"September 21, 2006","format":false,"excerpt":"I've spent the last two weeks working on getting [[Oracle]] into the role she was designed to play...but have found it to be a bit more involved than I realized. Originally, I set up the server to be a web server with php and sql capabilities. Then I realized I\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2007\/10\/oracle.png?fit=500%2C500&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":17,"url":"https:\/\/thepizzy.net\/blog\/2006\/03\/project-tsnxchat\/","url_meta":{"origin":1116,"position":1},"title":"Project: tsnXchat","author":"[[Neo]]","date":"March 1, 2006","format":false,"excerpt":"After using a flooble chatterbox from www.flooble.com, and trying to (unsuccessfully) hack it to get rid of the ads at the bottom, I have resolved to putting my newly developed AJAX skills to the test, to create an open-source version, with no ads. I'll explain how you can make one\u2026","rel":"","context":"In &quot;Projects&quot;","block_context":{"text":"Projects","link":"https:\/\/thepizzy.net\/blog\/category\/projects\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":71,"url":"https:\/\/thepizzy.net\/blog\/2006\/09\/oracle-reborn-tsnlocal-goes-up-beta\/","url_meta":{"origin":1116,"position":2},"title":"[[Oracle]] Reborn, tsnlocal goes up beta","author":"[[Neo]]","date":"September 11, 2006","format":false,"excerpt":"This weekend, I hung out with [wizard] and we worked on our servers. He created his [m3rlin] server, and I created my [[Oracle]] server. Originally, as you might recall from previous posts, [[Oracle]] is an IRC bot that we use for auto responding and chanserv purposes. Our bots are still\u2026","rel":"","context":"In &quot;Technology&quot;","block_context":{"text":"Technology","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2007\/10\/oracle.png?fit=500%2C500&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":56,"url":"https:\/\/thepizzy.net\/blog\/2006\/05\/were-number-1\/","url_meta":{"origin":1116,"position":3},"title":"&#8220;We&#8217;re number 1!!&#8221;","author":"[[Neo]]","date":"May 16, 2006","format":false,"excerpt":"Ok, so while coding the tsnX forums for the-spot.net, there were several instances in which the mods didn't work because everyone's mods assume (usually) that they are going to be the only mod installed in the forums. And while this is the ideology that saves time when writing a modification,\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":63,"url":"https:\/\/thepizzy.net\/blog\/2006\/06\/update-tsnx-database-movement\/","url_meta":{"origin":1116,"position":4},"title":"Update: tsnX Database Movement","author":"[[Neo]]","date":"June 9, 2006","format":false,"excerpt":"I'm backing up the tsnX.3 Beta's Database (with the posts, forums, and accounts) and going to start moving the tsnV database into the tsnX site. The site is going to be down for a bit, while I do this, and iron out the kinks of auth-access, and conversions. If things\u2026","rel":"","context":"In &quot;Projects&quot;","block_context":{"text":"Projects","link":"https:\/\/thepizzy.net\/blog\/category\/projects\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2008\/04\/Untitled-2.png?fit=400%2C400&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":99,"url":"https:\/\/thepizzy.net\/blog\/2008\/01\/poc-openvpn-internet-ms-exchange-active-directory-windowslinux-mobile-client\/","url_meta":{"origin":1116,"position":5},"title":"POC: OpenVPN + Internet + MS Exchange Active Directory + Windows\/Linux Mobile Client","author":"[[Neo]]","date":"January 18, 2008","format":false,"excerpt":"I have this idea, ok? What I noticed while migrating some of the users from the Admissions Department at the University for which I work, was that it was tough to explain to them sufficiently that: Their passwords are going to have to change at some point, due to security\u2026","rel":"","context":"In &quot;Technology&quot;","block_context":{"text":"Technology","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2008\/01\/outlook_2007_logo1.jpg?fit=428%2C419&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts\/1116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/comments?post=1116"}],"version-history":[{"count":18,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts\/1116\/revisions"}],"predecessor-version":[{"id":1657,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts\/1116\/revisions\/1657"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/media\/1125"}],"wp:attachment":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/media?parent=1116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/categories?post=1116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/tags?post=1116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}