/////////////////////////////////////////////////////////////////////// // This used to send the emails, but not now. Now it just queues // the emails to be sent, then spawns a thread to send them. public static void send_notifications(int insert_or_update, // The implementation int bugid, Security security, int just_to_this_userid, bool status_changed, bool assigned_to_changed, int prev_assigned_to_user) { // If there's something worth emailing about, then there's // probably something worth updating the index about. // Really, though, we wouldn't want to update the index if it were // just the status that were changing... if (btnet.Util.get_setting("EnableLucene", "1") == "1") { MyLucene.update_lucene_index(bugid); } bool notification_email_enabled = (btnet.Util.get_setting("NotificationEmailEnabled", "1") == "1"); if (!notification_email_enabled) { return; } // MAW -- 2006/01/27 -- Determine level of change detected int changeLevel = 0; if (insert_or_update == INSERT) { changeLevel = 1; } else if (status_changed) { changeLevel = 2; } else if (assigned_to_changed) { changeLevel = 3; } else { changeLevel = 4; } string sql; if (just_to_this_userid > 0) { sql = @" /* get notification email for just one user */ select us_email, us_id, us_admin, og.* from bug_subscriptions inner join users on bs_user = us_id inner join orgs og on us_org = og_id inner join bugs on bg_id = bs_bug left outer join project_user_xref on pu_user = us_id and pu_project = bg_project where us_email is not null and us_enable_notifications = 1 -- $status_change and us_active = 1 and us_email <> '' and case when us_org <> bg_org and og_other_orgs_permission_level < 2 and og_other_orgs_permission_level < isnull(pu_permission_level,$dpl) then og_other_orgs_permission_level else isnull(pu_permission_level,$dpl) end <> 0 and bs_bug = $id and us_id = $just_this_usid"; sql = sql.Replace("$just_this_usid", Convert.ToString(just_to_this_userid)); } else { // MAW -- 2006/01/27 -- Added different notifications if reported or assigned-to sql = @" /* get notification emails for all subscribers */ select us_email, us_id, us_admin, og.* from bug_subscriptions inner join users on bs_user = us_id inner join orgs og on us_org = og_id inner join bugs on bg_id = bs_bug left outer join project_user_xref on pu_user = us_id and pu_project = bg_project where us_email is not null and us_enable_notifications = 1 -- $status_change and us_active = 1 and us_email <> '' and ( ($cl <= us_reported_notifications and bg_reported_user = bs_user) or ($cl <= us_assigned_notifications and bg_assigned_to_user = bs_user) or ($cl <= us_assigned_notifications and $pau = bs_user) or ($cl <= us_subscribed_notifications)) and case when us_org <> bg_org and og_other_orgs_permission_level < 2 and og_other_orgs_permission_level < isnull(pu_permission_level,$dpl) then og_other_orgs_permission_level else isnull(pu_permission_level,$dpl) end <> 0 and bs_bug = $id and (us_id <> $us or isnull(us_send_notifications_to_self,0) = 1)"; } sql = sql.Replace("$cl", changeLevel.ToString()); sql = sql.Replace("$pau", prev_assigned_to_user.ToString()); sql = sql.Replace("$id", Convert.ToString(bugid)); sql = sql.Replace("$dpl", btnet.Util.get_setting("DefaultPermissionLevel", "2")); sql = sql.Replace("$us", Convert.ToString(security.user.usid)); DataSet ds_subscribers = btnet.DbUtil.get_dataset(sql); if (ds_subscribers.Tables[0].Rows.Count > 0) { bool added_to_queue = false; // Get bug html DataRow bug_dr = btnet.Bug.get_bug_datarow(bugid, security); string from = btnet.Util.get_setting("NotificationEmailFrom", ""); // Format the subject line string subject = btnet.Util.get_setting("NotificationSubjectFormat", "$THING$:$BUGID$ was $ACTION$ - $SHORTDESC$ $TRACKINGID$"); subject = subject.Replace("$THING$", btnet.Util.capitalize_first_letter(btnet.Util.get_setting("SingularBugLabel", "bug"))); string action = ""; if (insert_or_update == INSERT) { action = "added"; } else { action = "updated"; } subject = subject.Replace("$ACTION$", action); subject = subject.Replace("$BUGID$", Convert.ToString(bugid)); subject = subject.Replace("$SHORTDESC$", (string)bug_dr["short_desc"]); string tracking_id = " ("; tracking_id += btnet.Util.get_setting("TrackingIdString", "DO NOT EDIT THIS:"); tracking_id += Convert.ToString(bugid); tracking_id += ")"; subject = subject.Replace("$TRACKINGID$", tracking_id); subject = subject.Replace("$PROJECT$", (string)bug_dr["current_project"]); subject = subject.Replace("$ORGANIZATION$", (string)bug_dr["og_name"]); subject = subject.Replace("$CATEGORY$", (string)bug_dr["category_name"]); subject = subject.Replace("$PRIORITY$", (string)bug_dr["priority_name"]); subject = subject.Replace("$STATUS$", (string)bug_dr["status_name"]); subject = subject.Replace("$ASSIGNED_TO$", (string)bug_dr["assigned_to_username"]); // send a separate email to each subscriber foreach (DataRow dr in ds_subscribers.Tables[0].Rows) { string to = (string)dr["us_email"]; // Create a fake response and let the code // write the html to that response System.IO.StringWriter writer = new System.IO.StringWriter(); HttpResponse my_response = new HttpResponse(writer); my_response.Write("<html>"); my_response.Write("<base href=\"" + btnet.Util.get_setting("AbsoluteUrlPrefix", "http://127.0.0.1/") + "\"/>"); // create a security rec for the user receiving the email Security sec2 = new Security(); // fill in what we know is needed downstream sec2.user.is_admin = Convert.ToBoolean(dr["us_admin"]); sec2.user.external_user = Convert.ToBoolean(dr["og_external_user"]); sec2.user.tags_field_permission_level = (int)dr["og_category_field_permission_level"]; sec2.user.category_field_permission_level = (int)dr["og_category_field_permission_level"]; sec2.user.priority_field_permission_level = (int)dr["og_priority_field_permission_level"]; sec2.user.assigned_to_field_permission_level = (int)dr["og_assigned_to_field_permission_level"]; sec2.user.status_field_permission_level = (int)dr["og_status_field_permission_level"]; sec2.user.project_field_permission_level = (int)dr["og_project_field_permission_level"]; sec2.user.org_field_permission_level = (int)dr["og_org_field_permission_level"]; sec2.user.udf_field_permission_level = (int)dr["og_udf_field_permission_level"]; DataSet ds_custom = Util.get_custom_columns(); foreach (DataRow dr_custom in ds_custom.Tables[0].Rows) { string bg_name = (string)dr_custom["name"]; string og_name = "og_" + (string)dr_custom["name"] + "_field_permission_level"; object obj = dr[og_name]; if (Convert.IsDBNull(obj)) { sec2.user.dict_custom_field_permission_level[bg_name] = Security.PERMISSION_ALL; } else { sec2.user.dict_custom_field_permission_level[bg_name] = (int)dr[og_name]; } } PrintBug.print_bug( my_response, bug_dr, sec2, true, /* include style */ false, /* images_inline */ true /* history_inline */); // at this point "writer" has the bug html sql = @" delete from queued_notifications where qn_bug = $bug and qn_to = N'$to' insert into queued_notifications (qn_date_created, qn_bug, qn_user, qn_status, qn_retries, qn_to, qn_from, qn_subject, qn_body, qn_last_exception) values (getdate(), $bug, $user, N'not sent', 0, N'$to', N'$from', N'$subject', N'$body', N'')"; sql = sql.Replace("$bug", Convert.ToString(bugid)); sql = sql.Replace("$user", Convert.ToString(dr["us_id"])); sql = sql.Replace("$to", to.Replace("'", "''")); sql = sql.Replace("$from", from.Replace("'", "''")); sql = sql.Replace("$subject", subject.Replace("'", "''")); sql = sql.Replace("$body", writer.ToString().Replace("'", "''")); btnet.DbUtil.execute_nonquery_without_logging(sql); added_to_queue = true; } // end loop through ds_subscribers if (added_to_queue) { // spawn a worker thread to send the emails System.Threading.ThreadStart worker = new System.Threading.ThreadStart(threadproc_notifications); System.Threading.Thread thread = new System.Threading.Thread(worker); thread.Start(); } } // if there are any subscribers }
/////////////////////////////////////////////////////////////////////// // create a new index static void threadproc_build(object obj) { lock (my_lock) { try { System.Web.HttpApplicationState app = (System.Web.HttpApplicationState)obj; btnet.Util.write_to_log("started creating Lucene index using folder " + MyLucene.index_path); Lucene.Net.Index.IndexWriter writer = new Lucene.Net.Index.IndexWriter(index_path, anal, true); string sql = @" select bg_id, $custom_cols isnull(bg_tags,'') bg_tags, bg_short_desc from bugs"; DataSet ds_text_custom_cols = get_text_custom_cols(); sql = sql.Replace("$custom_cols", get_text_custom_cols_names(ds_text_custom_cols)); // index the bugs DataSet ds = btnet.DbUtil.get_dataset(sql); foreach (DataRow dr in ds.Tables[0].Rows) { // desc writer.AddDocument(MyLucene.create_doc( (int)dr["bg_id"], 0, "desc", (string)dr["bg_short_desc"])); // tags string tags = (string)dr["bg_tags"]; if (tags != "") { writer.AddDocument(MyLucene.create_doc( (int)dr["bg_id"], 0, "tags", tags)); } // custom text fields foreach (DataRow dr_custom_col in ds_text_custom_cols.Tables[0].Rows) { string name = (string)dr_custom_col["name"]; string val = Convert.ToString(dr[name]); if (val != "") { writer.AddDocument(MyLucene.create_doc( (int)dr["bg_id"], 0, name.Replace("'", "''"), val)); } } } // index the bug posts ds = btnet.DbUtil.get_dataset(@" select bp_bug, bp_id, isnull(bp_comment_search,bp_comment) [text] from bug_posts where bp_type <> 'update' and bp_hidden_from_external_users = 0"); foreach (DataRow dr in ds.Tables[0].Rows) { writer.AddDocument(MyLucene.create_doc( (int)dr["bp_bug"], (int)dr["bp_id"], "post", (string)dr["text"])); } writer.Optimize(); writer.Close(); btnet.Util.write_to_log("done creating Lucene index"); } catch (Exception e) { btnet.Util.write_to_log("exception building Lucene index: " + e.Message); } } }
// update an existing index static void threadproc_update(object obj) { // just to be safe, make the worker threads wait for each other //System.Console.Beep(540, 20); lock (my_lock) // prevent contention between searching and writing? { //System.Console.Beep(840, 20); try { if (searcher != null) { try { searcher.Close(); } catch (Exception e) { btnet.Util.write_to_log("Exception closing lucene searcher:" + e.Message); } searcher = null; } Lucene.Net.Index.IndexModifier modifier = new Lucene.Net.Index.IndexModifier(index_path, anal, false); // same as buid, but uses "modifier" instead of write. // uses additional "where" clause for bugid int bug_id = (int)obj; btnet.Util.write_to_log("started updating Lucene index using folder " + MyLucene.index_path); modifier.DeleteDocuments(new Lucene.Net.Index.Term("bg_id", Convert.ToString(bug_id))); string sql = @" select bg_id, $custom_cols isnull(bg_tags,'') bg_tags, bg_short_desc from bugs where bg_id = $bugid"; sql = sql.Replace("$bugid", Convert.ToString(bug_id)); DataSet ds_text_custom_cols = get_text_custom_cols(); sql = sql.Replace("$custom_cols", get_text_custom_cols_names(ds_text_custom_cols)); // index the bugs DataRow dr = btnet.DbUtil.get_datarow(sql); modifier.AddDocument(MyLucene.create_doc( (int)dr["bg_id"], 0, "desc", (string)dr["bg_short_desc"])); // tags string tags = (string)dr["bg_tags"]; if (tags != "") { modifier.AddDocument(MyLucene.create_doc( (int)dr["bg_id"], 0, "tags", tags)); } // custom text fields foreach (DataRow dr_custom_col in ds_text_custom_cols.Tables[0].Rows) { string name = (string)dr_custom_col["name"]; string val = Convert.ToString(dr[name]); if (val != "") { modifier.AddDocument(MyLucene.create_doc( (int)dr["bg_id"], 0, name.Replace("'", "''"), val)); } } // index the bug posts DataSet ds = btnet.DbUtil.get_dataset(@" select bp_bug, bp_id, isnull(bp_comment_search,bp_comment) [text] from bug_posts where bp_type <> 'update' and bp_hidden_from_external_users = 0 and bp_bug = " + Convert.ToString(bug_id)); foreach (DataRow dr2 in ds.Tables[0].Rows) { modifier.AddDocument(MyLucene.create_doc( (int)dr2["bp_bug"], (int)dr2["bp_id"], "post", (string)dr2["text"])); } modifier.Flush(); modifier.Close(); btnet.Util.write_to_log("done updating Lucene index"); } catch (Exception e) { btnet.Util.write_to_log("exception updating Lucene index: " + e.Message); } } }
public void Application_OnStart(Object sender, EventArgs e) { string path = HttpContext.Current.Server.MapPath(null); HttpRuntime.Cache.Add("MapPath", path, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); HttpRuntime.Cache.Add("Application", Application, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); string dir = path + "\\App_Data"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } dir = path + "\\App_Data\\logs"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } dir = path + "\\App_Data\\uploads"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } dir = path + "\\App_Data\\lucene_index"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } Util.set_context(HttpContext.Current); // required for map path calls to work in util.cs StreamReader sr = File.OpenText(path + "\\custom\\custom_header.html"); Application["custom_header"] = sr.ReadToEnd(); sr.Close(); sr = File.OpenText(path + "\\custom\\custom_footer.html"); Application["custom_footer"] = sr.ReadToEnd(); sr.Close(); sr = File.OpenText(path + "\\custom\\custom_logo.html"); Application["custom_logo"] = sr.ReadToEnd(); sr.Close(); sr = File.OpenText(path + "\\custom\\custom_welcome.html"); Application["custom_welcome"] = sr.ReadToEnd(); sr.Close(); if (Util.get_setting("EnableVotes", "0") == "1") { Tags.count_votes(Application); // in tags file for convenience for me.... } if (Util.get_setting("EnableTags", "0") == "1") { Tags.build_tag_index(Application); } if (Util.get_setting("EnableLucene", "1") == "1") { MyLucene.build_lucene_index(Application); } if (Util.get_setting("EnablePop3", "0") == "1") { MyPop3.start_pop3(Application); } }