December 2006 - Posts
UPDATE 04/18/2007:
This fix and several others apparently didn't make it into CS 2007, but this fix as presented is compatible with CS 2007. I will create a later post that includes all the fixes that didn't make it into CS 2007.
I can't believe I finally found a fix for this problem. I stumbled upon it while working on another problem. Here's the fix:
File: CommunityServerComponents(20)/Roles.cs:
Change the following method from:
public static string[] GetUserRoleNames(string username, bool cacheable)
{
string[] roles = null;
string key = "UserRoleNames:" + username.ToLower();
if (cacheable)
roles = CSCache.Get(key) as string[];
else
CSCache.Remove(key);
if (roles == null)
{
// there is a situation where the cookie may be using an old username, which can cause this call to fail, at this point
// we're too deep in the call tree to do anything else, so we just need to log the exception and force the
// user to signout since we're having problems pulling the user's roles from the database
try
{
roles = MemberRoleProfileProvider.Instance().Roles.GetRolesForUser(username);
if (cacheable)
CSCache.Insert(key, roles, 10 * CSCache.MinuteFactor);
}
catch (Exception e)
{
CSException cse = new CSException(CSExceptionType.RoleNotFound, String.Format("Error while trying to find a role for the user '{0}'. Possible cause is a invalid client cookie or a user rename.", username), e);
cse.Log();
if (CSContext.Current.RawUrl != HttpContext.Current.Request.RawUrl)
{
FormsAuthentication.SignOut();
HttpContext.Current.Response.Redirect(SiteUrls.Instance().Home);
}
}
}
return roles;
}
to:
public static string[] GetUserRoleNames(string username, bool cacheable)
{
string[] roles = null;
string key;
// there is a situation where the cookie may be using an old username, which can cause this call to fail, at this point
// we're too deep in the call tree to do anything else, so we just need to log the exception and force the
// user to signout since we're having problems pulling the user's roles from the database
try
{
key = "UserRoleNames:" + username.ToLower();
if (cacheable)
roles = CSCache.Get(key) as string[];
else
CSCache.Remove(key);
if (roles == null)
{
roles = MemberRoleProfileProvider.Instance().Roles.GetRolesForUser(username);
if (cacheable)
CSCache.Insert(key, roles, 10 * CSCache.MinuteFactor);
}
}
catch (Exception e)
{
CSException cse = new CSException(CSExceptionType.RoleNotFound, String.Format("Error while trying to find a role for the user '{0}'. Possible cause is a invalid client cookie or a user rename.", username), e);
cse.Log();
if (HttpContext.Current.Request.UrlReferrer.AbsolutePath != SiteUrls.Instance().Home)
{
FormsAuthentication.SignOut();
HttpContext.Current.Response.Redirect(SiteUrls.Instance().Home);
}
}
return roles;
}
Does the TinyMCE editor get you down? You you feel unpoopular? Whoops, thats a different issue. The current issue at hand is that the default user controls seem to have left out the ability to justify text even though the editor and CS both support it. Click here for a list of all the buttons/controls that TinyMCE supports. What we are going to do here is add the missing justification buttons to the "TinyMCE Enhanced" editor:
File: CommunityServerWeb(20)/Themes/default/Skins/Skin-Editor-Enhanced.ascx:
Find the line:
<TMCE:TinyMCEOption runat="server" Name="theme_advanced_buttons2" Value="'bold,italic,underline,strikethrough,separator,indent,outdent,separator,bullist,numlist,separator,link,unlink,image,contentselector,smiley'" />
and insert:
,separator,justifyleft,justifycenter,justifyright,justifyfull
after the word 'strikethrough'.
Believe it or not, you're done. Go ahead and try it. If you want, add more buttons/controls that TinyMCE supports. If you want to add these buttons to the "TinyMCE Standard" editor as well, do the following:
File: CommunityServerWeb(20)/Themes/default/Skins/Skin-Editor-Standard.ascx:
Find the line:
<TMCE:TinyMCEOption runat="server" Name="theme_advanced_buttons1_add" Value="'iespell'" />
and replace it with:
<TMCE:TinyMCEOption runat="server" Name="theme_advanced_buttons1" Value="'bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,indent,outdent,separator,bullist,numlist,separator,link,unlink,image,contentselector,smiley,separator,cut,copy,paste,pasteword,separator,code,iespell'" />
You might be asking, "Why did we replace the line here instead of inserting the missing text?" The answer is that the control that Telligent wrote is hard coded with a basic set of buttons to which they were just adding the 'iespell' button. So, we had to completely replace that basic list of buttons with the full list of buttons that we want to see.
I believe that the editor supports up to 4 or 5 menu lines, so go at it. Not everything may function properly as some of the functions require custom code to be written for your site. But you can try the different buttons, see what works, and decide what you want to provide.
This issue has come up a few times as the management of blogs by users is extremely cumbersome, and almost requires a degree in CS (Community Server, not Computer Science) to even get to the controls. With these changes you can easily add a "My Blogs" menu item that takes you to the blog selection pagein the "Control Panel".
This doesn't make the management any easier, but it does make it easier to get to the management (control panel) pages. Here are the changes:
File: SiteUrls.config:
Section: SiteUrls/locations:
After the line:
<location name="controlpanel" path="/controlpanel/" exclude="true" />
insert the line:
<location name="myweblogs" path="/controlpanel/blogs/" exclude="true" />
Section: SiteUrls/navigation:
After the line:
<link name="blog" resourceUrl="webloghome" resourceName="weblogs" roles="Everyone" applicationType="Weblog" />
insert the line:
<link name="myblogs" resourceUrl="mywebloghome" resourceName="MyWeblogs" roles="Registered Users" />
You may want to create a special role like "Blog Owners", assign the role to all blog owners, and use it in the roles attribute above instead of "Registered Users".
Section: SiteUrls/urls:
After the lines:
<!--
// Blogs
//
-->
insert the line:
<url name="mywebloghome" location="myweblogs" path="switch.aspx" />
UPDATE 03/01/2007: Click here for the latest update
This bug fix corrects the non-functioning read/unread flags in the forums. It corrects issues in 4 different stored procedures in CS 2.1 SP2. It has not been tested in a CS 2.1 RTM or CS 2.1 SP1 environment as I don't currently have either enviroment to test it on. The names of the stored procedures that have been changed are:
- cs_forums_Post
- cs_forums_threads_ThreadsRead
- cs_Post_CreateUpdate
- cs_Section_MarkRead
UPDATE 01/08/2007: While working with Shaan and his very large database, I have identified some performace issues and some issues with 3rd party patches or addons. If you have a 3rd party patch/addon, you will need to incorporate those changes into this bug fix. If you have any problems or questions, please contact me.
If you have a small to medium sized database, you should not have any problems with the fix that is currently available. However, if you have a large database, please contact me before you attempt to implement this bug fix. With Shaan's help, things are looking good and I hope to post an update soon.
WARNING: This bug fix was written for CS 2.1 SP2 and has not been tested on any other version.
You should backup your current database and/or these stored procedures as standard practice before applying any code changes. Click here to download the latest version of the bug fix.
If some one who is not logged in attempts to access a resource that requires them to be logged in, the site redirects them to a login page. If the user is registered, they just enter their login information and they able to access the resource. But if they aren't registered, many users don't notice the tiny "Join" option in the upper right corner, and get totally frustrated not being able to find it.
What I have done is add a "Join" button to the right of the "Sign In >>" button on the login page, to allow unregistered users to register. All you need to do is modify your "/Themes/default/Skins/Skin-Login.ascx" file to look like:
<%@ Control Language="C#" %>
<%@ Import Namespace="CommunityServer.Controls" %>
<%@ Import Namespace="CommunityServer.Components" %>
<%@ Register TagPrefix="CS" Namespace="CommunityServer.Controls" Assembly="CommunityServer.Controls" %>
<%@ Register TagPrefix="CSD" Namespace="CommunityServer.Discussions.Controls" Assembly="CommunityServer.Discussions" %>
<div align="center">
<div class="CommonMessageArea">
<h4 class="CommonMessageTitle">
<CS:ResourceLabel runat="server" ResourceName="Login_Title" />
</h4>
<div class="CommonMessageContent">
<div class="CommonFormArea">
<table cellspacing="1" border="0" cellpadding="5" width="100%">
<tr>
<td align="right" class="CommonFormFieldName">
<CS:ResourceLabel runat="server" ResourceName="Login_UserName" />
</td>
<td class="CommonFormField">
<CS:DefaultButtonTextBox CssClass="CommonTextBig" Button="loginButton" ID="username" runat="server" size="30" MaxLength="64" />
</td>
</tr>
<tr>
<td align="right" class="CommonFormFieldName">
<CS:ResourceLabel runat="server" ResourceName="Login_Password" />
</td>
<td class="CommonFormField">
<CS:DefaultButtonTextBox CssClass="CommonTextBig" Button="loginButton" TextMode="Password" ID="password" runat="server" size="11" MaxLength="64" />
<span class="txt4">(<CSD:ForumAnchor AnchorType="UserForgotPassword" runat="server" />)</span>
</td>
</tr>
<tr>
<td>
</td>
<td align="left" class="CommonFormField" nowrap>
<asp:CheckBox type="checkbox" Checked="true" runat="server" ID="autoLogin" />
</td>
</tr>
<tr>
<td class="CommonFormField" colspan="2" nowrap>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td align="center" width="50%">
<asp:LinkButton ID="loginButton" runat="server" CssClass="CommonTextButtonBig" /></td>
<td align="center" width="50%">
<a class="CommonTextButtonBig" href="<% =Globals.GetSiteUrls().UserRegister %>">
<% =ResourceManager.GetString("register") %>
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
The bolded text denotes the changed lines.
The following changes will notify of Private Message posts and tell you how many new posts that you have:
CommunityServerBlogs(20)/Controls/DisplayUserWelcome.cs and
CommunityServerControls(20)/Skins/DisplayUserWelcome.cs:
Replace the
AttachChildControls() method with:
protected override void AttachChildControls()
{
int privateMessageCount = 0;
string url = "";
string anchorClass;
// Only process if the user is signed in
if (!csContext.Context.Request.IsAuthenticated)
return;
Control privateMessages = FindControl("PrivateMessages");
if (privateMessages != null)
{
if (Users.EnablePM(csContext.User))
{
privateMessageCount = UserMessages.UnreadMessagesCount(csContext.User.UserID);
if (privateMessageCount > 0)
{
url = string.Format(ResourceManager.GetString("PrivateMessage_Unread"), privateMessageCount);
anchorClass = " class=\"NewPrivateMessage\"";
}
else
{
url = string.Format(ResourceManager.GetString("PrivateMessages_Messages"), privateMessageCount);
anchorClass = string.Empty;
}
// Set URL
url = string.Format("<a{0} href=\"{1}\">{2}</a>", anchorClass, Globals.GetSiteUrls().UserPrivateMessages, url);
// Add to control tree
privateMessages.Controls.Add(new LiteralControl(" | " + url));
}
else
{
privateMessages.Visible = false;
}
}
}
CommunityServerComponents(20)/UserMessages.cs:
Change the line:
CSCache.Insert(key, unreadCount, 3600);
to read:
CSCache.Insert(key, unreadCount, 60);
You could change the timeout value to 1 second or some other value, but 60 seconds is probably a good setting as 1 minute is the new CS standard for running site processes.
CommunityServerWeb(20)/Languages/en-US/Resources.xml:
Find the following 2 lines:
<resource name = "PrivateMessages_Messages"> Inbox</resource>
<resource name = "PrivateMessage_Unread">Inbox ({0})</resource>
and replace then with:
<resource name = "PrivateMessages_Messages">Inbox</resource>
<resource name = "PrivateMessage_Unread">Inbox ({0})</resource>
In the
Common.css file of every theme:
After the section:
#welcome A, #welcome A:VISITED, #welcome A:ACTIVE, #welcome A:HOVER
{
<snip>
}
insert:
/* This is the class that will override parent styles when a user has messages */
#welcome A.NewPrivateMessage, #welcome A.NewPrivateMessage:VISITED, #welcome A.NewPrivateMessage:ACTIVE, #welcome A.NewPrivateMessage:HOVER
{
color: #FF0000;
}