Background
Huddler is a company that provided free hosting for web forums for a cut of advertising revenue. They were acquired by Wikia who apparently didn't want anything to do with the web forum business and started ending their contracts with forum owners. A colleague contacted me for assistance in a migration of his forum and here some technical notes and experiences on the task. Huddler was generally courteous about the whole seperation process and gave forum owners time to find new hosts and prepare a migration plan. Full migrations were quite a chore as the Huddler DB schema was undocumented and the style markup of forum posts was a mash of BBCode and HTML that had changed through time.
Migration Goals
- Priority
- Users: Name, Email, Password, Profile Images / Information / Questions, Stats (Reputation, Post Counts)
- Threads:
- Thread name (and ID) shouldn't change to best preserve Google Juice.
- Thread posts: poster, post information and content (whole section on this one later).
- Polls: Question, Answers and Votes.
- Private Messages
- Registration IPs
- Poster IPs
Huddler Provided Data
- PostgreSQL 9.4 Database Dump
- Tarball of static images from Huddler's CDN.
Huddler / IPS Database Comparison
User table entries had a 1-1 migration. Profile images were normalized to a table external_store_objects which had a list of all the static images in the CDN.
Huddler | IPB |
---|---|
users | core_members |
perms_group_membership | Field on core_members |
Forums, Threads / Topics and Post entries had a 1-1 migration.
Huddler | IPB |
---|---|
forums | forums_forums |
forum_threads | forums_topics |
forum_posts | forums_posts |
Huddler's poll table has a 1-1 relationship with the core_polls table, but Huddler broke out all the possible answers for a poll into a separate poll_options table. IPS stores the available answers as a JSON on the core_polls table. Additionally, the Huddler association of a poll to a thread was stored in yet another table.
Huddler | IPB |
---|---|
poll | core_polls |
poll_options | Field on core_polls containing JSON |
poll_attach | Field on core_polls |
Also a pretty close 1-1 relationship. Migrating the user relationships with the messages was a bit trickier. To keep things simple, we didn't migrate draft or system messages (users were given a heads-up to save their drafts if they had any).
Huddler | IPB |
---|---|
message_thread | core_message_topics |
message | core_message_posts |
message_recipient | core_message_topic_user_map |
Password Hashing
Huddler used several different password hashing techniques, the only appeared to upgrade a users hash when the users changed their passwords (password hashes can also be upgraded when a user logs in). I found at least three: bcrypt ($2y$12$
) and two 32 character hashes, one with a salt field and one with a blank salt field. The first one md5( md5(password) + salt)
(a holdover from before Huddler when the system was VBulletin) and a third one that Huddler wouldn't divulge the mechanism. I tried about about two dozen combinations of md4 and md5 but was never succesfull in determining what hash mechanism they were using.
I extended the IPS Internal Login Handler (system/Login/Internal.php
) to authenticate and rehash the passwords using the bcrypt $2a$13$
when the users logged in. Users from the last group where the hash was unusable just had to reset their password.