diff -urN drupal-4.4.1/database/database.mysql drupal4blog/database/database.mysql
--- drupal-4.4.1/database/database.mysql	Sun May  2 23:45:29 2004
+++ drupal4blog/database/database.mysql	Tue May 18 01:23:10 2004
@@ -128,6 +128,7 @@
   status tinyint(3) unsigned NOT NULL default '0',
   thread varchar(255) NOT NULL,
   users longtext,
+  anon longtext,
   PRIMARY KEY  (cid),
   KEY lid (nid)
 ) TYPE=MyISAM;
@@ -301,6 +302,18 @@
 ) TYPE=MyISAM;
 
 --
+-- Table structure for table 'blog'
+--
+
+CREATE TABLE blog (
+  nid int(10) unsigned NOT NULL default '0',
+  extended longtext NOT NULL,
+  excerpt longtext NOT NULL,
+  format tinyint(2) NOT NULL default '0',
+  PRIMARY KEY  (nid)
+) TYPE=MyISAM;
+
+--
 -- Table structure for table 'page'
 --
 
@@ -570,29 +583,62 @@
 ) TYPE=MyISAM;
 
 --
+-- Table structure for table 'tb'
+--
+
+CREATE TABLE tb (
+  nid int(10) unsigned NOT NULL default '0',
+  pinged longtext,
+  toping longtext,
+  PRIMARY KEY  (nid)
+) TYPE=MyISAM;
+
+--
 -- Insert some default values
 --
 
 INSERT INTO system VALUES ('modules/admin.module','admin','module','',1,0,0);
+INSERT INTO system VALUES ('modules/archive.module','archive','module','',1,0,0);
 INSERT INTO system VALUES ('modules/block.module','block','module','',1,0,0);
 INSERT INTO system VALUES ('modules/comment.module','comment','module','',1,0,0);
 INSERT INTO system VALUES ('modules/help.module','help','module','',1,0,0);
 INSERT INTO system VALUES ('modules/node.module','node','module','',1,0,0);
-INSERT INTO system VALUES ('modules/page.module','page','module','',1,0,0);
-INSERT INTO system VALUES ('modules/story.module','story','module','',1,0,0);
+INSERT INTO system VALUES ('modules/blog.module','blog','module','',1,0,0);
+INSERT INTO system VALUES ('modules/blogadmin.module','blogadmin','module','',1,0,0);
+INSERT INTO system VALUES ('modules/ping.module','ping','module','',1,0,0);
+INSERT INTO system VALUES ('modules/search.module','search','module','',1,0,0);
 INSERT INTO system VALUES ('modules/taxonomy.module','taxonomy','module','',1,0,0);
+INSERT INTO system VALUES ('modules/profile.module','profile','module','',1,0,0);
+INSERT INTO system VALUES ('modules/tracker.module','tracker','module','',1,0,0);
+INSERT INTO system VALUES ('modules/trackback.module','trackback','module','',1,0,0);
+INSERT INTO system VALUES ('modules/upload.module', 'upload', 'module','',1,0,0);
+INSERT INTO system VALUES ('modules/urlfilter.module', 'urlfilter', 'module','',1,0,0);
+
 INSERT INTO system VALUES ('themes/xtemplate/xtemplate.theme','xtemplate','theme','Internet explorer, Netscape, Opera',1,0,0);
+
 INSERT INTO users (uid, name, mail, rid) VALUES ('0', '', '', '1');
 
 INSERT INTO role (rid, name) VALUES (1, 'anonymous user');
-INSERT INTO permission VALUES (1,'access content',0);
+INSERT INTO permission VALUES (1,'access comments, access content, access trackback, post trackback, post comments, download files (simple)',0);
 
 INSERT INTO role (rid, name) VALUES (2, 'authenticated user');
-INSERT INTO permission VALUES (2,'access comments, access content, post comments, post comments without approval',0);
+INSERT INTO permission VALUES (2,'access comments, access content, access trackback, post trackback, post comments, post comments without approval, download files (simple)',0);
+
+INSERT INTO role (rid, name) VALUES (3, 'blogger');
+INSERT INTO permission VALUES (3,'access comments, access content, access trackback, administer comments, post trackback, post comments, post comments without approval, create blog entry, edit own blog, download files (simple), upload files (simple), maintain files (simple)',0);
 
 REPLACE variable SET name='update_start', value='s:10:"2004-02-21;"';
 REPLACE variable SET name='theme_default', value='s:9:"xtemplate";';
 
-REPLACE blocks SET module = 'user', delta = '0', status = '1';
-REPLACE blocks SET module = 'user', delta = '1', status = '1';
+REPLACE blocks SET module = 'user', delta = '0', status = '1', weight='8';
+REPLACE blocks SET module = 'user', delta = '1', status = '1', weight='10';
+REPLACE blocks SET module = 'blog', delta = '0', status = '1';
+REPLACE blocks SET module = 'blogadmin', delta = '0', status = '1', weight='-5';
+REPLACE blocks SET module = 'archive', delta = '0', status = '1', weight='-10';
+
+# enable real name and homepage by default
+INSERT INTO variable VALUES ( 'profile_private_fields', 'a:20:{i:0;s:1:"0";i:1;s:8:"realname";i:2;s:1:"0";i:3;s:1:"0";i:4;s:1:"0";i:5;s:1:"0";i:6;s:1:"0";i:7;s:1:"0";i:8;s:1:"0";i:9;s:1:"0";i:10;s:1:"0";i:11;s:1:"0";i:12;s:1:"0";i:13;s:1:"0";i:14;s:1:"0";i:15;s:8:"homepage";i:16;s:1:"0";i:17;s:1:"0";i:18;s:1:"0";i:19;s:1:"0";}' );
+
+INSERT INTO variable VALUES ( 'profile_public_fields', 'a:20:{i:0;s:1:"0";i:1;s:8:"realname";i:2;s:1:"0";i:3;s:1:"0";i:4;s:1:"0";i:5;s:1:"0";i:6;s:1:"0";i:7;s:1:"0";i:8;s:1:"0";i:9;s:1:"0";i:10;s:1:"0";i:11;s:1:"0";i:12;s:1:"0";i:13;s:1:"0";i:14;s:1:"0";i:15;s:8:"homepage";i:16;s:1:"0";i:17;s:1:"0";i:18;s:1:"0";i:19;s:1:"0";}' );
 
+INSERT INTO vocabulary VALUES (1, 'Category', 'Categories for Blog Entries', 0, 0, 1, 0, 'blog', 0);
diff -urN drupal-4.4.1/database/database.pgsql drupal4blog/database/database.pgsql
--- drupal-4.4.1/database/database.pgsql	Sun May  2 23:45:29 2004
+++ drupal4blog/database/database.pgsql	Thu Jan  1 07:30:00 1970
@@ -1,615 +0,0 @@
--- PostgreSQL include file 31/10/2002
--- Maintainer: James Arthur, j_a_arthurATyahooDOTcom
-
---
--- Table structure for access
---
-
-CREATE TABLE access (
-  aid SERIAL,
-  mask varchar(255) NOT NULL default '',
-  type varchar(255) NOT NULL default '',
-  status smallint NOT NULL default '0',
-  PRIMARY KEY (aid),
-  UNIQUE (mask)
-);
-
---
--- Table structure for accesslog
---
-
-CREATE TABLE accesslog (
-  nid integer default '0',
-  url varchar(255) default NULL,
-  hostname varchar(128) default NULL,
-  uid integer default '0',
-  timestamp integer NOT NULL default '0'
-);
-CREATE INDEX accesslog_timestamp_idx ON accesslog (timestamp);
-
---
--- Table structure for authmap
---
-
-CREATE TABLE authmap (
-  aid SERIAL,
-  uid integer NOT NULL default '0',
-  authname varchar(128) NOT NULL default '',
-  module varchar(128) NOT NULL default '',
-  PRIMARY KEY (aid),
-  UNIQUE (authname)
-);
-
---
--- Table structure for blocks
---
-
-CREATE TABLE blocks (
-  module varchar(64) NOT NULL default '',
-  delta varchar(32) NOT NULL default '0',
-  status smallint NOT NULL default '0',
-  weight smallint NOT NULL default '0',
-  region smallint NOT NULL default '0',
-  path varchar(255) NOT NULL default '',
-  custom smallint NOT NULL default '0',
-  throttle smallint NOT NULL default '0'
-);
-
---
--- Table structure for book
---
-
-CREATE TABLE book (
-  nid integer NOT NULL default '0',
-  parent integer NOT NULL default '0',
-  weight smallint NOT NULL default '0',
-  format smallint default '0',
-  log text default '',
-  PRIMARY KEY (nid)
-);
-CREATE INDEX book_nid_idx ON book(nid);
-CREATE INDEX book_parent ON book(parent);
-
---
--- Table structure for boxes
---
-
-CREATE TABLE boxes (
-  bid SERIAL,
-  title varchar(64) NOT NULL default '',
-  body text default '',
-  info varchar(128) NOT NULL default '',
-  type smallint NOT NULL default '0',
-  PRIMARY KEY  (bid),
-  UNIQUE (info),
-  UNIQUE (title)
-);
-
---
--- Table structure for bundle
---
-
-CREATE TABLE bundle (
-  bid SERIAL,
-  title varchar(255) NOT NULL default '',
-  attributes varchar(255) NOT NULL default '',
-  PRIMARY KEY  (bid),
-  UNIQUE (title)
-);
-
---
--- Table structure for cache
---
-
-CREATE TABLE cache (
-  cid varchar(255) NOT NULL default '',
-  data text default '',
-  expire integer NOT NULL default '0',
-  created integer NOT NULL default '0',
-  headers text default '',
-  PRIMARY KEY  (cid)
-);
-
---
--- Table structure for comments
---
-
-CREATE TABLE comments (
-  cid SERIAL,
-  pid integer NOT NULL default '0',
-  nid integer NOT NULL default '0',
-  uid integer NOT NULL default '0',
-  subject varchar(64) NOT NULL default '',
-  comment text NOT NULL default '',
-  hostname varchar(128) NOT NULL default '',
-  timestamp integer NOT NULL default '0',
-  score integer NOT NULL default '0',
-  status smallint  NOT NULL default '0',
-  thread varchar(255) default '',
-  users text default '',
-  PRIMARY KEY  (cid)
-);
-CREATE INDEX comments_nid_idx ON comments(nid);
-
---
--- Table structure for directory
---
-
-CREATE TABLE directory (
-  link varchar(255) NOT NULL default '',
-  name varchar(128) NOT NULL default '',
-  mail varchar(128) NOT NULL default '',
-  slogan text NOT NULL default '',
-  mission text NOT NULL default '',
-  timestamp integer NOT NULL default '0',
-  PRIMARY KEY  (link)
-);
-
---
--- Table structure for feed
---
-
-CREATE TABLE feed (
-  fid SERIAL,
-  title varchar(255) NOT NULL default '',
-  url varchar(255) NOT NULL default '',
-  refresh integer NOT NULL default '0',
-  checked integer NOT NULL default '0',
-  attributes varchar(255) NOT NULL default '',
-  link varchar(255) NOT NULL default '',
-  description text NOT NULL default '',
-  image text NOT NULL default '',
-  etag varchar(255) NOT NULL default '',
-  modified integer NOT NULL default '0',
-  PRIMARY KEY  (fid),
-  UNIQUE (title),
-  UNIQUE (url)
-);
-
---
--- Table structure for table 'filters'
---
-
-CREATE TABLE filters (
-  module varchar(64) NOT NULL default '',
-  weight smallint DEFAULT '0' NOT NULL,
-  PRIMARY KEY (weight)
-);
-
---
--- Table structure for table 'forum'
---
-
-CREATE TABLE forum (
-  nid integer NOT NULL default '0',
-  tid integer NOT NULL default '0',
-  shadow integer NOT NULL default '0',
-  PRIMARY KEY  (nid)
-);
-CREATE INDEX forum_tid_idx ON forum(tid);
-
---
--- Table structure for history
---
-
-CREATE TABLE history (
-  uid integer NOT NULL default '0',
-  nid integer NOT NULL default '0',
-  timestamp integer NOT NULL default '0',
-  PRIMARY KEY  (uid,nid)
-);
-
---
--- Table structure for item
---
-
-CREATE TABLE item (
-  iid SERIAL,
-  fid integer NOT NULL default '0',
-  title varchar(255) NOT NULL default '',
-  link varchar(255) NOT NULL default '',
-  author varchar(255) NOT NULL default '',
-  description text NOT NULL default '',
-  timestamp integer NOT NULL default '0',
-  attributes varchar(255) NOT NULL default '',
-  PRIMARY KEY  (iid)
-);
-
---
--- Table structure for locales
---
-
-CREATE TABLE locales (
-  lid SERIAL,
-  location varchar(128) NOT NULL default '',
-  string text NOT NULL default '',
-  da text NOT NULL default '',
-  fi text NOT NULL default '',
-  fr text NOT NULL default '',
-  en text NOT NULL default '',
-  es text NOT NULL default '',
-  nl text NOT NULL default '',
-  no text NOT NULL default '',
-  sw text NOT NULL default '',
-  PRIMARY KEY  (lid)
-);
-
---
--- Table structure for table 'moderation_filters'
---
-
-CREATE TABLE moderation_filters (
-  fid SERIAL,
-  filter varchar(255) NOT NULL default '',
-  minimum smallint NOT NULL default '0',
-  PRIMARY KEY  (fid)
-);
-
---
--- Table structure for table 'moderation_roles'
---
-
-CREATE TABLE moderation_roles (
-  rid integer NOT NULL default '0',
-  mid integer NOT NULL default '0',
-  value smallint NOT NULL default '0'
-);
-CREATE INDEX moderation_roles_rid_idx ON moderation_roles(rid);
-CREATE INDEX moderation_roles_mid_idx ON moderation_roles(mid);
-
---
--- Table structure for table 'moderation_votes'
---
-
-CREATE TABLE moderation_votes (
-  mid SERIAL,
-  vote varchar(255) default NULL,
-  weight smallint NOT NULL default '0',
-  PRIMARY KEY  (mid)
-);
-
---
--- Table structure for node
---
-
-CREATE TABLE node (
-  nid SERIAL,
-  type varchar(16) NOT NULL default '',
-  title varchar(128) NOT NULL default '',
-  score integer NOT NULL default '0',
-  votes integer NOT NULL default '0',
-  uid integer NOT NULL default '0',
-  status integer NOT NULL default '1',
-  created integer NOT NULL default '0',
-  comment integer NOT NULL default '0',
-  promote integer NOT NULL default '0',
-  moderate integer NOT NULL default '0',
-  users text NOT NULL default '',
-  teaser text NOT NULL default '',
-  body text NOT NULL default '',
-  changed integer NOT NULL default '0',
-  revisions text NOT NULL default '',
-  static integer NOT NULL default '0',
-  PRIMARY KEY  (nid)
-);
-CREATE INDEX node_type_idx ON node(type);
-CREATE INDEX node_title_idx ON node(title,type);
-CREATE INDEX node_status_idx ON node(status);
-CREATE INDEX node_uid_idx ON node(uid);
-CREATE INDEX node_moderate_idx ON node (moderate);
-CREATE INDEX node_promote_status_idx ON node (promote, status);
-
---
--- Table structure for table 'node_counter'
---
-
-CREATE TABLE node_counter (
-  nid integer NOT NULL default '0',
-  totalcount integer NOT NULL default '0',
-  daycount integer NOT NULL default '0',
-  timestamp integer NOT NULL default '0',
-  PRIMARY KEY  (nid)
-);
-CREATE INDEX node_counter_totalcount_idx ON node_counter(totalcount);
-CREATE INDEX node_counter_daycount_idx ON node_counter(daycount);
-CREATE INDEX node_counter_timestamp_idx ON node_counter(timestamp);
-
---
--- Table structure for page
---
-
-CREATE TABLE page (
-  nid integer NOT NULL default '0',
-  link varchar(128) NOT NULL default '',
-  format smallint NOT NULL default '0',
-  description varchar(128) NOT NULL default '',
-  PRIMARY KEY  (nid)
-);
-CREATE INDEX page_nid_idx ON page(nid);
-
---
--- Table structure for table 'url_alias'
---
-
-CREATE TABLE url_alias (
-  pid serial,
-  dst varchar(128) NOT NULL default '',
-  src varchar(128) NOT NULL default '',
-  PRIMARY KEY  (pid)
-);
-CREATE INDEX url_alias_src_idx ON url_alias(src);
-CREATE INDEX url_alias_dst_idx ON url_alias(dst);
---
--- Table structure for permission
---
-
-CREATE TABLE permission (
-  rid integer NOT NULL default '0',
-  perm text default '',
-  tid integer NOT NULL default '0'
-);
-CREATE INDEX permission_rid_idx ON permission(rid);
-
---
--- Table structure for poll
---
-
-CREATE TABLE poll (
-  nid integer NOT NULL default '0',
-  runtime integer NOT NULL default '0',
-  voters text NOT NULL default '',
-  active integer NOT NULL default '0',
-  PRIMARY KEY  (nid)
-);
-
---
--- Table structure for poll_choices
---
-
-CREATE TABLE poll_choices (
-  chid SERIAL,
-  nid integer NOT NULL default '0',
-  chtext varchar(128) NOT NULL default '',
-  chvotes integer NOT NULL default '0',
-  chorder integer NOT NULL default '0',
-  PRIMARY KEY  (chid)
-);
-CREATE INDEX poll_choices_nid_idx ON poll_choices(nid);
-
---
--- Table structure for role
---
-
-CREATE TABLE role (
-  rid SERIAL,
-  name varchar(32) NOT NULL default '',
-  PRIMARY KEY  (rid),
-  UNIQUE (name)
-);
-
---
--- Table structure for search_index
---
-
-CREATE TABLE search_index (
-  word varchar(50) NOT NULL default '',
-  lno integer NOT NULL default '0',
-  type varchar(16) default NULL,
-  count integer default NULL
-);
-CREATE INDEX search_index_lno_idx ON search_index(lno);
-CREATE INDEX search_index_word_idx ON search_index(word);
-
---
--- Table structure for sessions
---
-
-CREATE TABLE sessions (
-  uid integer NOT NULL,
-  sid varchar(32) NOT NULL default '',
-  hostname varchar(128) NOT NULL default '',
-  timestamp integer NOT NULL default '0',
-  session text,
-  PRIMARY KEY (sid)
-);
-
---
--- Table structure for sequences
--- This is only used under MySQL, co commented out
---
---
--- CREATE TABLE sequences (
---   name varchar(255) NOT NULL,
---   id integer NOT NULL,
---   PRIMARY KEY (name)
--- );
-
---
--- Table structure for system
---
-
-CREATE TABLE system (
-  filename varchar(255) NOT NULL default '',
-  name varchar(255) NOT NULL default '',
-  type varchar(255) NOT NULL default '',
-  description varchar(255) NOT NULL default '',
-  status integer NOT NULL default '0',
-  throttle smallint NOT NULL default '0',
-  bootstrap integer NOT NULL default '0',
-  PRIMARY KEY  (filename)
-);
-
---
--- Table structure for term_data
---
-
-CREATE TABLE term_data (
-  tid SERIAL,
-  vid integer NOT NULL default '0',
-  name varchar(255) NOT NULL default '',
-  description text default '',
-  weight smallint NOT NULL default '0',
-  PRIMARY KEY  (tid)
-);
-CREATE INDEX term_data_vid_idx ON term_data(vid);
-
---
--- Table structure for term_hierarchy
---
-
-CREATE TABLE term_hierarchy (
-  tid integer NOT NULL default '0',
-  parent integer NOT NULL default '0'
-);
-CREATE INDEX term_hierarchy_tid_idx ON term_hierarchy(tid);
-CREATE INDEX term_hierarchy_parent_idx ON term_hierarchy(parent);
-
---
--- Table structure for term_node
---
-
-CREATE TABLE term_node (
-  nid integer NOT NULL default '0',
-  tid integer NOT NULL default '0'
-);
-CREATE INDEX term_node_nid_idx ON term_node(nid);
-CREATE INDEX term_node_tid_idx ON term_node(tid);
-
---
--- Table structure for term_relation
---
-
-CREATE TABLE term_relation (
-  tid1 integer NOT NULL default '0',
-  tid2 integer NOT NULL default '0'
-);
-CREATE INDEX term_relation_tid1_idx ON term_relation(tid1);
-CREATE INDEX term_relation_tid2_idx ON term_relation(tid2);
-
---
--- Table structure for term_synonym
---
-
-CREATE TABLE term_synonym (
-  tid integer NOT NULL default '0',
-  name varchar(255) NOT NULL default ''
-);
-CREATE INDEX term_synonym_tid_idx ON term_synonym(tid);
-CREATE INDEX term_synonym_name_idx ON term_synonym(name);
-
---
--- Table structure for users
---
-
-CREATE TABLE users (
-  uid integer NOT NULL default '0',
-  name varchar(60) NOT NULL default '',
-  pass varchar(32) NOT NULL default '',
-  mail varchar(64) default '',
-  mode smallint NOT NULL default '0',
-  sort smallint default '0',
-  threshold smallint default '0',
-  theme varchar(255) NOT NULL default '',
-  signature varchar(255) NOT NULL default '',
-  timestamp integer NOT NULL default '0',
-  status smallint NOT NULL default '0',
-  timezone varchar(8) default NULL,
-  language char(2) NOT NULL default '',
-  init varchar(64) default '',
-  data text default '',
-  rid integer NOT NULL default '0',
-  PRIMARY KEY  (uid),
-  UNIQUE (name)
-);
-CREATE INDEX users_timestamp_idx ON users(timestamp);
-
-CREATE SEQUENCE users_uid_seq INCREMENT 1 START 1;
-
---
--- Table structure for variable
---
-
-CREATE TABLE variable (
-  name varchar(48) NOT NULL default '',
-  value text NOT NULL default '',
-  PRIMARY KEY  (name)
-);
-
---
--- Table structure for vocabulary
---
-
-CREATE TABLE vocabulary (
-  vid SERIAL,
-  name varchar(255) NOT NULL default '',
-  description text default '',
-  relations smallint NOT NULL default '0',
-  hierarchy smallint NOT NULL default '0',
-  multiple smallint NOT NULL default '0',
-  required smallint NOT NULL default '0',
-  nodes text default '',
-  weight smallint NOT NULL default '0',
-  PRIMARY KEY  (vid)
-);
-
---
--- Table structure for watchdog
---
-
-CREATE TABLE watchdog (
-  wid SERIAL,
-  uid integer NOT NULL default '0',
-  type varchar(16) NOT NULL default '',
-  message text NOT NULL default '',
-  link varchar(255) NOT NULL default '',
-  location varchar(128) NOT NULL default '',
-  hostname varchar(128) NOT NULL default '',
-  timestamp integer NOT NULL default '0',
-  PRIMARY KEY  (wid)
-);
-
---
--- Insert some default values
---
-
-INSERT INTO system VALUES ('modules/admin.module','admin','module','',1,0,0);
-INSERT INTO system VALUES ('modules/block.module','block','module','',1,0,0);
-INSERT INTO system VALUES ('modules/comment.module','comment','module','',1,0,0);
-INSERT INTO system VALUES ('modules/help.module','help','module','',1,0,0);
-INSERT INTO system VALUES ('modules/node.module','node','module','',1,0,0);
-INSERT INTO system VALUES ('modules/page.module','page','module','',1,0,0);
-INSERT INTO system VALUES ('modules/story.module','story','module','',1,0,0);
-INSERT INTO system VALUES ('modules/taxonomy.module','taxonomy','module','',1,0,0);
-INSERT INTO system VALUES ('themes/xtemplate/xtemplate.theme','xtemplate','theme','Internet explorer, Netscape, Opera',1,0,0);
-
-INSERT INTO variable(name,value) VALUES('update_start', 's:10:"2004-02-21";');
-INSERT INTO variable(name,value) VALUES('theme_default','s:9:"xtemplate";');
-INSERT INTO users(uid,name,mail,rid) VALUES(0,'','', '1');
-
-INSERT INTO role (rid, name) VALUES (1, 'anonymous user');
-INSERT INTO permission VALUES (1,'access content',0);
-
-INSERT INTO role (rid, name) VALUES (2, 'authenticated user');
-INSERT INTO permission VALUES (2,'access comments, access content, post comments, post comments without approval',0);
-
-INSERT INTO blocks(module,delta,status) VALUES('user', '0', '1');
-INSERT INTO blocks(module,delta,status) VALUES('user', '1', '1');
-
----
---- Functions
----
-
-CREATE FUNCTION "greatest"(integer, integer) RETURNS integer AS '
-BEGIN
-  IF $1 > $2 THEN
-    RETURN $1;
-  END IF;
-  RETURN $2;
-END;
-' LANGUAGE 'plpgsql';
-
-CREATE FUNCTION "rand"() RETURNS float AS '
-BEGIN
-  RETURN random();
-END;
-' LANGUAGE 'plpgsql';
diff -urN drupal-4.4.1/database/database.pgsql.not.working.yet drupal4blog/database/database.pgsql.not.working.yet
--- drupal-4.4.1/database/database.pgsql.not.working.yet	Thu Jan  1 07:30:00 1970
+++ drupal4blog/database/database.pgsql.not.working.yet	Tue May 18 01:23:10 2004
@@ -0,0 +1,615 @@
+-- PostgreSQL include file 31/10/2002
+-- Maintainer: James Arthur, j_a_arthurATyahooDOTcom
+
+--
+-- Table structure for access
+--
+
+CREATE TABLE access (
+  aid SERIAL,
+  mask varchar(255) NOT NULL default '',
+  type varchar(255) NOT NULL default '',
+  status smallint NOT NULL default '0',
+  PRIMARY KEY (aid),
+  UNIQUE (mask)
+);
+
+--
+-- Table structure for accesslog
+--
+
+CREATE TABLE accesslog (
+  nid integer default '0',
+  url varchar(255) default NULL,
+  hostname varchar(128) default NULL,
+  uid integer default '0',
+  timestamp integer NOT NULL default '0'
+);
+CREATE INDEX accesslog_timestamp_idx ON accesslog (timestamp);
+
+--
+-- Table structure for authmap
+--
+
+CREATE TABLE authmap (
+  aid SERIAL,
+  uid integer NOT NULL default '0',
+  authname varchar(128) NOT NULL default '',
+  module varchar(128) NOT NULL default '',
+  PRIMARY KEY (aid),
+  UNIQUE (authname)
+);
+
+--
+-- Table structure for blocks
+--
+
+CREATE TABLE blocks (
+  module varchar(64) NOT NULL default '',
+  delta varchar(32) NOT NULL default '0',
+  status smallint NOT NULL default '0',
+  weight smallint NOT NULL default '0',
+  region smallint NOT NULL default '0',
+  path varchar(255) NOT NULL default '',
+  custom smallint NOT NULL default '0',
+  throttle smallint NOT NULL default '0'
+);
+
+--
+-- Table structure for book
+--
+
+CREATE TABLE book (
+  nid integer NOT NULL default '0',
+  parent integer NOT NULL default '0',
+  weight smallint NOT NULL default '0',
+  format smallint default '0',
+  log text default '',
+  PRIMARY KEY (nid)
+);
+CREATE INDEX book_nid_idx ON book(nid);
+CREATE INDEX book_parent ON book(parent);
+
+--
+-- Table structure for boxes
+--
+
+CREATE TABLE boxes (
+  bid SERIAL,
+  title varchar(64) NOT NULL default '',
+  body text default '',
+  info varchar(128) NOT NULL default '',
+  type smallint NOT NULL default '0',
+  PRIMARY KEY  (bid),
+  UNIQUE (info),
+  UNIQUE (title)
+);
+
+--
+-- Table structure for bundle
+--
+
+CREATE TABLE bundle (
+  bid SERIAL,
+  title varchar(255) NOT NULL default '',
+  attributes varchar(255) NOT NULL default '',
+  PRIMARY KEY  (bid),
+  UNIQUE (title)
+);
+
+--
+-- Table structure for cache
+--
+
+CREATE TABLE cache (
+  cid varchar(255) NOT NULL default '',
+  data text default '',
+  expire integer NOT NULL default '0',
+  created integer NOT NULL default '0',
+  headers text default '',
+  PRIMARY KEY  (cid)
+);
+
+--
+-- Table structure for comments
+--
+
+CREATE TABLE comments (
+  cid SERIAL,
+  pid integer NOT NULL default '0',
+  nid integer NOT NULL default '0',
+  uid integer NOT NULL default '0',
+  subject varchar(64) NOT NULL default '',
+  comment text NOT NULL default '',
+  hostname varchar(128) NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  score integer NOT NULL default '0',
+  status smallint  NOT NULL default '0',
+  thread varchar(255) default '',
+  users text default '',
+  PRIMARY KEY  (cid)
+);
+CREATE INDEX comments_nid_idx ON comments(nid);
+
+--
+-- Table structure for directory
+--
+
+CREATE TABLE directory (
+  link varchar(255) NOT NULL default '',
+  name varchar(128) NOT NULL default '',
+  mail varchar(128) NOT NULL default '',
+  slogan text NOT NULL default '',
+  mission text NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  PRIMARY KEY  (link)
+);
+
+--
+-- Table structure for feed
+--
+
+CREATE TABLE feed (
+  fid SERIAL,
+  title varchar(255) NOT NULL default '',
+  url varchar(255) NOT NULL default '',
+  refresh integer NOT NULL default '0',
+  checked integer NOT NULL default '0',
+  attributes varchar(255) NOT NULL default '',
+  link varchar(255) NOT NULL default '',
+  description text NOT NULL default '',
+  image text NOT NULL default '',
+  etag varchar(255) NOT NULL default '',
+  modified integer NOT NULL default '0',
+  PRIMARY KEY  (fid),
+  UNIQUE (title),
+  UNIQUE (url)
+);
+
+--
+-- Table structure for table 'filters'
+--
+
+CREATE TABLE filters (
+  module varchar(64) NOT NULL default '',
+  weight smallint DEFAULT '0' NOT NULL,
+  PRIMARY KEY (weight)
+);
+
+--
+-- Table structure for table 'forum'
+--
+
+CREATE TABLE forum (
+  nid integer NOT NULL default '0',
+  tid integer NOT NULL default '0',
+  shadow integer NOT NULL default '0',
+  PRIMARY KEY  (nid)
+);
+CREATE INDEX forum_tid_idx ON forum(tid);
+
+--
+-- Table structure for history
+--
+
+CREATE TABLE history (
+  uid integer NOT NULL default '0',
+  nid integer NOT NULL default '0',
+  timestamp integer NOT NULL default '0',
+  PRIMARY KEY  (uid,nid)
+);
+
+--
+-- Table structure for item
+--
+
+CREATE TABLE item (
+  iid SERIAL,
+  fid integer NOT NULL default '0',
+  title varchar(255) NOT NULL default '',
+  link varchar(255) NOT NULL default '',
+  author varchar(255) NOT NULL default '',
+  description text NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  attributes varchar(255) NOT NULL default '',
+  PRIMARY KEY  (iid)
+);
+
+--
+-- Table structure for locales
+--
+
+CREATE TABLE locales (
+  lid SERIAL,
+  location varchar(128) NOT NULL default '',
+  string text NOT NULL default '',
+  da text NOT NULL default '',
+  fi text NOT NULL default '',
+  fr text NOT NULL default '',
+  en text NOT NULL default '',
+  es text NOT NULL default '',
+  nl text NOT NULL default '',
+  no text NOT NULL default '',
+  sw text NOT NULL default '',
+  PRIMARY KEY  (lid)
+);
+
+--
+-- Table structure for table 'moderation_filters'
+--
+
+CREATE TABLE moderation_filters (
+  fid SERIAL,
+  filter varchar(255) NOT NULL default '',
+  minimum smallint NOT NULL default '0',
+  PRIMARY KEY  (fid)
+);
+
+--
+-- Table structure for table 'moderation_roles'
+--
+
+CREATE TABLE moderation_roles (
+  rid integer NOT NULL default '0',
+  mid integer NOT NULL default '0',
+  value smallint NOT NULL default '0'
+);
+CREATE INDEX moderation_roles_rid_idx ON moderation_roles(rid);
+CREATE INDEX moderation_roles_mid_idx ON moderation_roles(mid);
+
+--
+-- Table structure for table 'moderation_votes'
+--
+
+CREATE TABLE moderation_votes (
+  mid SERIAL,
+  vote varchar(255) default NULL,
+  weight smallint NOT NULL default '0',
+  PRIMARY KEY  (mid)
+);
+
+--
+-- Table structure for node
+--
+
+CREATE TABLE node (
+  nid SERIAL,
+  type varchar(16) NOT NULL default '',
+  title varchar(128) NOT NULL default '',
+  score integer NOT NULL default '0',
+  votes integer NOT NULL default '0',
+  uid integer NOT NULL default '0',
+  status integer NOT NULL default '1',
+  created integer NOT NULL default '0',
+  comment integer NOT NULL default '0',
+  promote integer NOT NULL default '0',
+  moderate integer NOT NULL default '0',
+  users text NOT NULL default '',
+  teaser text NOT NULL default '',
+  body text NOT NULL default '',
+  changed integer NOT NULL default '0',
+  revisions text NOT NULL default '',
+  static integer NOT NULL default '0',
+  PRIMARY KEY  (nid)
+);
+CREATE INDEX node_type_idx ON node(type);
+CREATE INDEX node_title_idx ON node(title,type);
+CREATE INDEX node_status_idx ON node(status);
+CREATE INDEX node_uid_idx ON node(uid);
+CREATE INDEX node_moderate_idx ON node (moderate);
+CREATE INDEX node_promote_status_idx ON node (promote, status);
+
+--
+-- Table structure for table 'node_counter'
+--
+
+CREATE TABLE node_counter (
+  nid integer NOT NULL default '0',
+  totalcount integer NOT NULL default '0',
+  daycount integer NOT NULL default '0',
+  timestamp integer NOT NULL default '0',
+  PRIMARY KEY  (nid)
+);
+CREATE INDEX node_counter_totalcount_idx ON node_counter(totalcount);
+CREATE INDEX node_counter_daycount_idx ON node_counter(daycount);
+CREATE INDEX node_counter_timestamp_idx ON node_counter(timestamp);
+
+--
+-- Table structure for page
+--
+
+CREATE TABLE page (
+  nid integer NOT NULL default '0',
+  link varchar(128) NOT NULL default '',
+  format smallint NOT NULL default '0',
+  description varchar(128) NOT NULL default '',
+  PRIMARY KEY  (nid)
+);
+CREATE INDEX page_nid_idx ON page(nid);
+
+--
+-- Table structure for table 'url_alias'
+--
+
+CREATE TABLE url_alias (
+  pid serial,
+  dst varchar(128) NOT NULL default '',
+  src varchar(128) NOT NULL default '',
+  PRIMARY KEY  (pid)
+);
+CREATE INDEX url_alias_src_idx ON url_alias(src);
+CREATE INDEX url_alias_dst_idx ON url_alias(dst);
+--
+-- Table structure for permission
+--
+
+CREATE TABLE permission (
+  rid integer NOT NULL default '0',
+  perm text default '',
+  tid integer NOT NULL default '0'
+);
+CREATE INDEX permission_rid_idx ON permission(rid);
+
+--
+-- Table structure for poll
+--
+
+CREATE TABLE poll (
+  nid integer NOT NULL default '0',
+  runtime integer NOT NULL default '0',
+  voters text NOT NULL default '',
+  active integer NOT NULL default '0',
+  PRIMARY KEY  (nid)
+);
+
+--
+-- Table structure for poll_choices
+--
+
+CREATE TABLE poll_choices (
+  chid SERIAL,
+  nid integer NOT NULL default '0',
+  chtext varchar(128) NOT NULL default '',
+  chvotes integer NOT NULL default '0',
+  chorder integer NOT NULL default '0',
+  PRIMARY KEY  (chid)
+);
+CREATE INDEX poll_choices_nid_idx ON poll_choices(nid);
+
+--
+-- Table structure for role
+--
+
+CREATE TABLE role (
+  rid SERIAL,
+  name varchar(32) NOT NULL default '',
+  PRIMARY KEY  (rid),
+  UNIQUE (name)
+);
+
+--
+-- Table structure for search_index
+--
+
+CREATE TABLE search_index (
+  word varchar(50) NOT NULL default '',
+  lno integer NOT NULL default '0',
+  type varchar(16) default NULL,
+  count integer default NULL
+);
+CREATE INDEX search_index_lno_idx ON search_index(lno);
+CREATE INDEX search_index_word_idx ON search_index(word);
+
+--
+-- Table structure for sessions
+--
+
+CREATE TABLE sessions (
+  uid integer NOT NULL,
+  sid varchar(32) NOT NULL default '',
+  hostname varchar(128) NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  session text,
+  PRIMARY KEY (sid)
+);
+
+--
+-- Table structure for sequences
+-- This is only used under MySQL, co commented out
+--
+--
+-- CREATE TABLE sequences (
+--   name varchar(255) NOT NULL,
+--   id integer NOT NULL,
+--   PRIMARY KEY (name)
+-- );
+
+--
+-- Table structure for system
+--
+
+CREATE TABLE system (
+  filename varchar(255) NOT NULL default '',
+  name varchar(255) NOT NULL default '',
+  type varchar(255) NOT NULL default '',
+  description varchar(255) NOT NULL default '',
+  status integer NOT NULL default '0',
+  throttle smallint NOT NULL default '0',
+  bootstrap integer NOT NULL default '0',
+  PRIMARY KEY  (filename)
+);
+
+--
+-- Table structure for term_data
+--
+
+CREATE TABLE term_data (
+  tid SERIAL,
+  vid integer NOT NULL default '0',
+  name varchar(255) NOT NULL default '',
+  description text default '',
+  weight smallint NOT NULL default '0',
+  PRIMARY KEY  (tid)
+);
+CREATE INDEX term_data_vid_idx ON term_data(vid);
+
+--
+-- Table structure for term_hierarchy
+--
+
+CREATE TABLE term_hierarchy (
+  tid integer NOT NULL default '0',
+  parent integer NOT NULL default '0'
+);
+CREATE INDEX term_hierarchy_tid_idx ON term_hierarchy(tid);
+CREATE INDEX term_hierarchy_parent_idx ON term_hierarchy(parent);
+
+--
+-- Table structure for term_node
+--
+
+CREATE TABLE term_node (
+  nid integer NOT NULL default '0',
+  tid integer NOT NULL default '0'
+);
+CREATE INDEX term_node_nid_idx ON term_node(nid);
+CREATE INDEX term_node_tid_idx ON term_node(tid);
+
+--
+-- Table structure for term_relation
+--
+
+CREATE TABLE term_relation (
+  tid1 integer NOT NULL default '0',
+  tid2 integer NOT NULL default '0'
+);
+CREATE INDEX term_relation_tid1_idx ON term_relation(tid1);
+CREATE INDEX term_relation_tid2_idx ON term_relation(tid2);
+
+--
+-- Table structure for term_synonym
+--
+
+CREATE TABLE term_synonym (
+  tid integer NOT NULL default '0',
+  name varchar(255) NOT NULL default ''
+);
+CREATE INDEX term_synonym_tid_idx ON term_synonym(tid);
+CREATE INDEX term_synonym_name_idx ON term_synonym(name);
+
+--
+-- Table structure for users
+--
+
+CREATE TABLE users (
+  uid integer NOT NULL default '0',
+  name varchar(60) NOT NULL default '',
+  pass varchar(32) NOT NULL default '',
+  mail varchar(64) default '',
+  mode smallint NOT NULL default '0',
+  sort smallint default '0',
+  threshold smallint default '0',
+  theme varchar(255) NOT NULL default '',
+  signature varchar(255) NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  status smallint NOT NULL default '0',
+  timezone varchar(8) default NULL,
+  language char(2) NOT NULL default '',
+  init varchar(64) default '',
+  data text default '',
+  rid integer NOT NULL default '0',
+  PRIMARY KEY  (uid),
+  UNIQUE (name)
+);
+CREATE INDEX users_timestamp_idx ON users(timestamp);
+
+CREATE SEQUENCE users_uid_seq INCREMENT 1 START 1;
+
+--
+-- Table structure for variable
+--
+
+CREATE TABLE variable (
+  name varchar(48) NOT NULL default '',
+  value text NOT NULL default '',
+  PRIMARY KEY  (name)
+);
+
+--
+-- Table structure for vocabulary
+--
+
+CREATE TABLE vocabulary (
+  vid SERIAL,
+  name varchar(255) NOT NULL default '',
+  description text default '',
+  relations smallint NOT NULL default '0',
+  hierarchy smallint NOT NULL default '0',
+  multiple smallint NOT NULL default '0',
+  required smallint NOT NULL default '0',
+  nodes text default '',
+  weight smallint NOT NULL default '0',
+  PRIMARY KEY  (vid)
+);
+
+--
+-- Table structure for watchdog
+--
+
+CREATE TABLE watchdog (
+  wid SERIAL,
+  uid integer NOT NULL default '0',
+  type varchar(16) NOT NULL default '',
+  message text NOT NULL default '',
+  link varchar(255) NOT NULL default '',
+  location varchar(128) NOT NULL default '',
+  hostname varchar(128) NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  PRIMARY KEY  (wid)
+);
+
+--
+-- Insert some default values
+--
+
+INSERT INTO system VALUES ('modules/admin.module','admin','module','',1,0,0);
+INSERT INTO system VALUES ('modules/block.module','block','module','',1,0,0);
+INSERT INTO system VALUES ('modules/comment.module','comment','module','',1,0,0);
+INSERT INTO system VALUES ('modules/help.module','help','module','',1,0,0);
+INSERT INTO system VALUES ('modules/node.module','node','module','',1,0,0);
+INSERT INTO system VALUES ('modules/page.module','page','module','',1,0,0);
+INSERT INTO system VALUES ('modules/story.module','story','module','',1,0,0);
+INSERT INTO system VALUES ('modules/taxonomy.module','taxonomy','module','',1,0,0);
+INSERT INTO system VALUES ('themes/xtemplate/xtemplate.theme','xtemplate','theme','Internet explorer, Netscape, Opera',1,0,0);
+
+INSERT INTO variable(name,value) VALUES('update_start', 's:10:"2004-02-21";');
+INSERT INTO variable(name,value) VALUES('theme_default','s:9:"xtemplate";');
+INSERT INTO users(uid,name,mail,rid) VALUES(0,'','', '1');
+
+INSERT INTO role (rid, name) VALUES (1, 'anonymous user');
+INSERT INTO permission VALUES (1,'access content',0);
+
+INSERT INTO role (rid, name) VALUES (2, 'authenticated user');
+INSERT INTO permission VALUES (2,'access comments, access content, post comments, post comments without approval',0);
+
+INSERT INTO blocks(module,delta,status) VALUES('user', '0', '1');
+INSERT INTO blocks(module,delta,status) VALUES('user', '1', '1');
+
+---
+--- Functions
+---
+
+CREATE FUNCTION "greatest"(integer, integer) RETURNS integer AS '
+BEGIN
+  IF $1 > $2 THEN
+    RETURN $1;
+  END IF;
+  RETURN $2;
+END;
+' LANGUAGE 'plpgsql';
+
+CREATE FUNCTION "rand"() RETURNS float AS '
+BEGIN
+  RETURN random();
+END;
+' LANGUAGE 'plpgsql';
diff -urN drupal-4.4.1/modules/blog.module drupal4blog/modules/blog.module
--- drupal-4.4.1/modules/blog.module	Sun May  2 23:45:30 2004
+++ drupal4blog/modules/blog.module	Tue May 18 01:23:10 2004
@@ -2,17 +2,27 @@
 // $Id: blog.module,v 1.168.2.1 2004/03/15 19:41:47 dries Exp $
 
 function blog_settings() {
-  $output = form_textarea(t("Explanation or submission guidelines"), "blog_help", variable_get("blog_help", ""), 70, 4, t("This text is displayed at the top of the blog submission form.  It's useful for helping or instructing your users."));
-  $output .= form_select(t("Minimum number of words in a blog entry"), "minimum_blog_size", variable_get("minimum_blog_size", 0), drupal_map_assoc(array(0, 10, 25, 50, 75, 100, 125, 150, 175, 200)), t("The minimum number of words a personal blog entry should contain.  This is useful to rule out submissions that do not meet the site's standards, such as short test posts."));
+  $group = form_textarea(t("Explanation or submission guidelines"), "blog_help", variable_get("blog_help", ""), 70, 4, t("This text is displayed at the top of the blog submission form.  It's useful for helping or instructing your users."));
+  $group .= form_select(t("Minimum number of words in a blog entry"), "minimum_blog_size", variable_get("minimum_blog_size", 0), drupal_map_assoc(array(0, 10, 25, 50, 75, 100, 125, 150, 175, 200)), t("The minimum number of words a blog entry should contain.  This is useful to rule out submissions that do not meet the site's standards, such as short test posts."));
+  $output = form_group(t('Blog Entry settings'), $group);
+
+  $group = form_textfield(t("Block title"), "blog_block_title", variable_get("blog_block_title", "Recent Entries"), 70, 180, t("") . " " . t("Title of the Blog block, e.g. Recent Entries"));
+  $group .= form_select(t("Numbers of Entries"), "blog_block_entries", variable_get("blog_block_entries", 10), drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 50)), t("Numbers of last entries to display in block."));
+  $output .= form_group(t('Blog Block settings'), $group);
+
+  $group = form_select(t("RSS feed"), "blog_syndicate_rss", variable_get("blog_syndicate_rss",0), array(0 => "Full entry in RSS", 1 => "Teaser in RSS"), t("Format of the entries in syndication"));
+  $group .= form_select(t("Number of entries"), "blog_syndicate_entries", variable_get("blog_syndicate_entries", 15), drupal_map_assoc(array(10, 15, 20, 25, 30, 50)), t("Number of last entries to display in syndicate."));
+  $output .= form_group(t('Syndicate settings'),$group);
+
   return $output;
 }
 
 function blog_node_name($node) {
-  return t("personal blog entry");
+  return t("blog entry");
 }
 
 function blog_perm() {
-  return array("edit own blog");
+  return array("create blog entry", "edit own blog");
 }
 
 function blog_access($op, $node) {
@@ -23,7 +33,7 @@
   }
 
   if ($op == "create") {
-    return user_access("edit own blog") && $user->uid;
+    return user_access("create blog entry");
   }
 
   if ($op == "update") {
@@ -36,13 +46,43 @@
 
 }
 
+/**
+ * Respond to node insertion.
+ */
+function blog_insert($node) {
+  db_query("INSERT INTO {blog} (nid, extended, excerpt, format, status) VALUES (%d, '%s', '%s', %d, %d)", $node->nid, $node->extended, $node->excerpt, $node->format, $node->status);
+}
+
+/**
+ * Respond to node updating.
+ */
+function blog_update($node) {
+  db_query("UPDATE {blog} SET extended = '%s', excerpt = '%s', format = %d, status = %d WHERE nid = %d", $node->extended, $node->excerpt, $node->format, $node->status, $node->nid);
+}
+
+/**
+ * Respond to node deletion
+ */
+function blog_delete(&$node) {
+  db_query("DELETE FROM {blog} WHERE nid = %d", $node->nid);
+}
+
+/**
+ * Load node-type-specific information.
+ */
+function blog_load($node) {
+  return db_fetch_object(db_query("SELECT extended, excerpt, format, status FROM {blog} WHERE nid = %d", $node->nid));
+}
+
 function blog_user($type, &$edit, &$user) {
   switch ($type) {
     case "view_public":
     case "view_private":
+      $output = "";
       if (user_access("edit own blog", $user)) {
-        return form_item(t("Blog"), l(t("view recent blog entries"), "blog/$user->uid", array("title" => t("Read %username's latest blog entries.", array("%username" => $user->name)))));
+        $output .= form_item(t("Blog"), l(t("view recent blog entries"), "blog/$user->uid", array("title" => t("Read %username's latest blog entries.", array("%username" => $user->name)))));
       }
+      return $output;
   }
 }
 
@@ -54,7 +94,7 @@
       $output .= t("
       <p>Drupal's blog module allows registered users to maintain an online weblog (commonly known as a blog), often referred to as an online journal or diary.  These can be filled with daily thoughts, poetry, boneless blabber, spiritual theories, intimate details, valuable experiences, cynical rants, semi-coherent comments, writing experiments, artistic babblings, critics on current facts, fresh insights, diverse dreams, chronicles and mumbling madness available for public consumption.</p>
       <p>Blogs are made up of individual entries (nodes) that are timestamped and are typically viewed by day as you would a diary.  Blogs often contain links to things you've seen and/or agree/disagree with.  A typical example of a long term blog can be seen at %scripting-com.</p>
-      <p>The blog module adds a \"user blogs\" navigation link to the site, which takes any visitor to a page that displays the most recent blog entries from all the users on the site. Personal user menus gain a \"create a blog entry\" link (which takes you to a submission form) and a \"view personal blog\" link (which displays your blog entries as other people will see them).  On the bottom of each of your own blog entries, there is an \"edit this blog entry\" link that lets you edit or delete that entry.</p>
+      <p>The blog module adds a \"user blogs\" navigation link to the site, which takes any visitor to a page that displays the most recent blog entries from all the users on the site. Personal user menus gain a \"create a blog entry\" link (which takes you to a submission form) and a \"view blog\" link (which displays your blog entries as other people will see them).  On the bottom of each of your own blog entries, there is an \"edit this blog entry\" link that lets you edit or delete that entry.</p>
       <p>If a user has the ability to post blogs, then the import module (news aggregator) will display a blog-it link <strong>(b)</strong> next to each news item in its lists.  Click on this and you will be taken to the blog submission form, with the title, a link to the item, and a link to the source into the body text already in the text box, ready for you to add your explanation.  This actively encourages people to add blog entries about things they see and hear elsewhere in the Drupal site and from your syndicated partner sites.</p>", array("%scripting-com" => "<a href=\"http://www.scripting.com/\">http://www.scripting.com/</a>"));
       break;
     case 'admin/system/modules#description':
@@ -84,19 +124,19 @@
     $account = $user;
   }
 
-  $result = db_query_range("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'blog' AND u.uid = %d AND n.status = 1 ORDER BY n.nid DESC", $uid, 0, 15);
+  $result = db_query_range("SELECT * FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'blog' AND u.uid = %d AND n.status = 1 ORDER BY n.nid DESC", $uid, 0, variable_get("blog_syndicate_entries", 15));
   $channel["title"] = $account->name ."'s blog";
-  $channel["link"] = url("blog/view/$uid", NULL, NULL, TRUE);
-  $channel["description"] = $term->description;
-  node_feed($result, $channel);
+  $channel["link"] = url("blog/$uid", NULL, NULL, TRUE);
+  $channel["description"] = variable_get('site_mission','');
+  _blog_feed($result, $channel);
 }
 
 function blog_feed_last() {
-  $result = db_query_range("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.nid DESC", 0, 15);
-  $channel["title"] = variable_get("site_name", "drupal") ." blogs";
-  $channel["link"] = url("blog");
-  $channel["description"] = $term->description;
-  node_feed($result, $channel);
+  $result = db_query_range("SELECT *  FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.nid DESC", 0, variable_get("blog_syndicate_entries",15));
+  $channel["title"] = variable_get("site_name", "drupal");
+  $channel["link"] = url("", NULL, NULL, TRUE);
+  $channel["description"] = variable_get('site_mission','');
+  _blog_feed($result, $channel);
 }
 
 function blog_page_user($uid) {
@@ -139,7 +179,7 @@
   ** Validate the size of the blog:
   */
 
-  if (isset($node->body) && count(explode(" ", $node->body)) < variable_get("minimum_blog_size", 0)) {
+  if (isset($node->body) && count(explode(" ", $node->body." ".$node->extended)) < variable_get("minimum_blog_size", 0)) {
     $error["body"] = theme("error", t("The body of your blog is too short."));
   }
 
@@ -170,7 +210,14 @@
     $output .= implode("", taxonomy_node_form("blog", $node));
   }
 
-  $output .= form_textarea(t("Body"), "body", $node->body, 60, 15, $error["body"] ? $error["body"] : filter_tips_short());
+  $output .= form_textarea(t("Entry Body"), "body", $node->body, 60, 10, "");
+
+  $output .= form_textarea(t("Extended Entry"), "extended", $node->extended, 60, 15, "");
+
+  $output .= form_textarea(t("Excerpt"), "excerpt", $node->excerpt, 60, 5, $error["body"] ? $error["body"] : filter_tips_short());
+
+  $format_type = array(-1 => "No formatting", 0 => "Convert Line Breaks", 1 => "Simple Wiki");
+  $output .= form_select(t("Text Formatting"), "format", $node->format, $format_type, t("'Convert Line Breaks' enclose your paragraph in &lt;p&gt; and &lt;/p&gt; tag for you which is what most bloggers are used to. 'No formatting' assume you will do all HTML formatting. 'Simple Wiki' supports very basic Wiki Formatting Rules."));
 
   return $output;
 }
@@ -197,7 +244,7 @@
 }
 
 function blog_content($node, $main = 0) {
-  return node_prepare($node, $main);
+  return _blog_prepare($node, $main);
 }
 
 function blog_view($node, $main = 0, $page = 0) {
@@ -223,7 +270,7 @@
   if ($type == "system") {
     if (user_access("edit own blog")) {
       menu("node/add/blog", t("blog entry"), "node_page", 0);
-      menu("blog/". $user->uid, t("my blog"), "blog_page", 1);
+      menu("blog/". $user->uid, t("blog archives"), "blog_page", 1);
     }
     if (user_access("access content")) {
       menu("blog", t("blogs"), "blog_page", 0, MENU_HIDE);
@@ -235,7 +282,7 @@
   }
 
   if ($type == "node" && $node->type == "blog") {
-    if (blog_access("update", $node)) {
+    if (blog_access("update", $node) && !user_access('administer nodes')) {
       $links[] = l(t("edit this blog entry"), "node/edit/$node->nid", array("title" => t("Edit this blog entry.")));
     }
     elseif (arg(0) != 'blog' && arg(1) != $node->uid) {
@@ -254,12 +301,229 @@
   }
   else {
     if (user_access("access content")) {
-      $block["content"] = node_title_list(db_query_range("SELECT n.title, n.nid FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.nid DESC", 0, 10));
+      $block["content"] = node_title_list(db_query_range("SELECT n.title, n.nid FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.nid DESC", 0, variable_get("blog_block_entries",10)));
+      $block["content"] .= theme('xml_icon', url('blog/feed'));
       $block["content"] .= "<div class=\"more-link\">". l(t("more"), "blog", array("title" => t("Read the latest blog entries."))) ."</div>";
-      $block["subject"] = t("Blogs");
+      $block["subject"] = variable_get("blog_block_title", "Recent Entries");
     }
     return $block;
   }
+}
+
+
+/*
+ * modified from check_output() from filter.module
+ */
+function check_output_without_nl2br($text) {
+  if (isset($text)) {
+    // Filter content on output:
+    $filters = filter_list();
+
+    // Give filters the chance to escape HTML-like data such as code or formulas
+    // (from this point on, the input can be treated as HTML)
+    if (variable_get("filter_html", FILTER_HTML_DONOTHING) != FILTER_HTML_ESCAPE) {
+      foreach ($filters as $module => $filter) {
+        $text = module_invoke($module, "filter", "prepare", $text);
+      }
+    }
+
+    // HTML handling is done before all regular filtering activities
+    $text = filter_default($text);
+
+    // Regular filtering
+    foreach ($filters as $module => $filter) {
+      $text = module_invoke($module, "filter", "process", $text);
+    }
+  }
+  else {
+    $text = message_na();
+  }
+
+  return $text;
+}
+
+function blog_blogadmin($type = "") {
+  $list = array();
+
+  if ($type == "block") {
+    if (user_access("create blog entry"))
+      $list[] = l(t("new blog entry"), "node/add/blog");
+  } else if ($type == "blog") {
+    if (user_access("administer site configuration")) {
+      $list[l(t("Blog entries options"),"admin/system/modules/blog")] = t("Define options for your blog entries and RSS syndication.");
+    }
+  }
+
+  return $list;
+}
+
+function _blog_process_format($node,$str) {
+  if ($node->format < 0) {
+    return check_output_without_nl2br($str);
+  }
+
+  // Convert Line Breaks
+  if ($node->format == 0) {
+    $paras = preg_split("/\r?\n\r?\n/",$str);
+    foreach ($paras as $id => $p) {
+      if (!$p) continue;
+      $paras[$id] = "<p>". check_output($p) ."</p>";
+    }
+    return implode("\n\n",$paras);
+  }
+
+  // Simple Wiki
+  if ($node->format == 1) {
+    //include_once "modules/wiki.module";
+    //return _wiki_transform($str);
+    $wiki_search = array(
+      "/('*)'''(.*?)'''/",
+      "/''(.*)''/",
+      "/----+/",
+      "/\[(http|https|ftp|mailto):(\S+)\s+([^\]]+)\]/",
+      "/^(http|https|ftp):\/\/(\S+)(gif|jpg|png|bmp|jpeg)/",
+      "/([^\"\[])(http|https|ftp|mailto):(\S+)/",
+    );
+
+    $wiki_replace = array(
+      "\\1<strong>\\2</strong>",
+      "<em>\\1</em>",
+      "<hr/>",
+      "<a href=\"\\1:\\2\">\\3</a>",
+      "<img src=\"\\1://\\2\\3\" /><br/>",
+      "\\1<a href=\"\\2:\\3\">\\2:\\3</a>",
+    );
+
+    $paras = preg_split("/\r?\n\r?\n/",$str);
+    foreach ($paras as $id => $p) {
+      $paras[$id] = "<p>" .  check_output(
+         preg_replace($wiki_search,$wiki_replace,$p)) . "</p>";
+    }
+    return implode("\n\n",$paras);
+  }
+
+  return $str;
+}
+
+function _blog_prepare($node,$main = 0) {
+    $node->readmore = (strlen($node->extended) > 0 
+                   || strlen($node->excerpt > 0));
+    if ($main == 0) {
+        $str = rtrim($node->body) . "\n\n" . rtrim($node->extended);
+        $node->body = _blog_process_format($node,$str);
+    } else {
+        if (strlen(rtrim($node->excerpt)) > 0) 
+            $node->teaser = _blog_process_format($node,rtrim($node->excerpt));
+        else
+            $node->teaser = _blog_process_format($node,rtrim($node->body));
+    }
+    return $node;
+}
+
+/*
+** based on node_feed
+*/
+function _blog_feed($nodes = 0, $channel = array()) {
+  global $base_url, $languages;
+
+  /*
+  ** A generic function for generating RSS feeds from a set of nodes.
+  **   - $nodes should be an object as returned by db_query() which contains
+  **     the nid field.
+  **   - $channel is an associative array containing title, link,
+  **     description and other keys. The link should be an absolute URL.
+  */
+
+  if (!$nodes) {
+    return blog_feed_last();
+  }
+
+  while ($node = db_fetch_object($nodes)) {
+    /*
+    ** Load the specified node:
+    */
+
+    $item = node_load(array('nid' => $node->nid));
+    $link = url("node/view/$node->nid", NULL, NULL, 1);
+
+    switch (variable_get("blog_syndicate_rss",0)) {
+      case 0:
+        $node = _blog_prepare($item,0);
+        $desc = drupal_specialchars($node->body);
+        break;
+      case 1:
+        $node = _blog_prepare($item,1);
+        $node->teaser .= "...<a href=\"$base_url/$links\">read more</a>";
+        $desc = drupal_specialchars($node->teaser);
+        break;
+    }
+    $items .= _blog_format_rss_item($item->title, $link, $desc, 
+      array(
+        'dc:date' => iso8601_date($item->changed),
+        'dc:creator' => $item->name,
+# need to add category/taxonomy info
+      )
+    );
+  }
+
+  $channel_defaults = array(
+    'version'     => '0.92',
+    'title'       => variable_get('site_name', 'drupal') .' - '. variable_get('site_slogan', ''),
+    'link'        => $base_url,
+    'description' => variable_get('site_mission', ''),
+    'language'    => (($key = reset(array_keys($languages))) ? $key : 'en')
+  );
+  $channel = array_merge($channel_defaults, $channel);
+
+  $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+  $output .= "<!DOCTYPE rss [<!ENTITY % HTMLlat1 PUBLIC \"-//W3C//ENTITIES Latin 1 for XHTML//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent\">]>\n";
+  $output .= "<rss version=\"". $channel["version"] . "\" xml:base=\"". $base_url ."\">\n";
+  $output .= _blog_format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language'], array(
+    'dc:creator' => variable_get('site_mail',''),
+  ));
+  $output .= "</rss>\n";
+
+  drupal_set_header('Content-Type: text/xml; charset=utf-8');
+  print $output;
+}
+
+function _blog_format_rss_item($title, $link, $description, $args = array()) {
+  // arbitrary elements may be added using the $args associative array
+  $output = "<item>\n";
+  $output .= " <title>". drupal_specialchars(strip_tags($title)) ."</title>\n";
+  $output .= " <link>". drupal_specialchars(strip_tags($link)) ."</link>\n";
+  $output .= " <description>". $description ."</description>\n";
+  foreach ($args as $key => $value) {
+    $output .= "<$key>". drupal_specialchars(strip_tags($value)) ."</$key>";
+  }
+  $output .= "</item>\n";
+
+  return $output;
+}
+
+function _blog_format_rss_channel($title, $link, $description, $items, $language = "en", $args = array()) {
+  // arbitrary elements may be added using the $args associative array
+
+  $output = "<channel>\n";
+  $output .= " <title>". drupal_specialchars(strip_tags($title)) ."</title>\n";
+  $output .= " <link>". drupal_specialchars(strip_tags($link)) ."</link>\n";
+  $output .= " <description>". $description ."</description>\n";
+  $output .= " <language>". drupal_specialchars(strip_tags($language)) ."</language>\n";
+  foreach ($args as $key => $value) {
+    $output .= " <$key>". drupal_specialchars(strip_tags($value)) ."</$key>\n";
+  }
+  $output .= $items;
+  $output .= "</channel>\n";
+
+  return $output;
+}
+
+function iso8601_date($time) {
+  $tzd = date('O',$time);
+  $tzd = $tzd[0] . str_pad((int) ($tzd/100),2,"0",STR_PAD_LEFT) . ":" .
+                   str_pad((int) ($tzd%100),2,"0",STR_PAD_LEFT);
+  $date = date('Y-m-d\TG:i:s',$time).$tzd;
+  return $date;
 }
 
 ?>
diff -urN drupal-4.4.1/modules/blogadmin.module drupal4blog/modules/blogadmin.module
--- drupal-4.4.1/modules/blogadmin.module	Thu Jan  1 07:30:00 1970
+++ drupal4blog/modules/blogadmin.module	Tue May 18 01:23:10 2004
@@ -0,0 +1,87 @@
+<?php
+
+function blogadmin_help($section) {
+  switch ($section) {
+    case "admin/system/modules#description":
+      return t("Provides simple blog administration block. (Requires: drupal4blog patches)");
+  }
+}
+
+function blogadmin_link($type) {
+  if ($type == "system")
+    menu("blogadmin", t("blogadmin"), "blogadmin_page", 0, MENU_HIDE);
+}
+
+function blogadmin_page() {
+  $type = strip_tags(arg(1));
+
+  switch (arg(1)) {
+    case "options":
+      $output = blogadmin_default($type);
+      break;
+      
+    default:
+      $output = blogadmin_default("page");
+      break;
+  }
+  print $output;
+}
+
+function blogadmin_default($type = "page") {
+  $menu = module_invoke_all("blogadmin",$type);
+
+  /*
+  ** These should goes into the respective *_blogadmin() but leave it here
+  ** because we do not want to change too many modules
+  */
+  if ($type == "options") {
+  
+    if (user_access("administer site configuration")) {
+      if (module_exist("archive"))
+        $menu[l(t("Archive options"),"admin/system/modules/archive")] = t("Configure archive options");
+    }
+  }
+
+  $output = "";
+
+  foreach ($menu as $l => $m) {
+    $output .= "<ul><li>".$l."<ul><li>".$m."</li></ul></li></ul>\n";
+  }
+
+  if ($type == "options") return theme("page",$output, t("Options"));
+
+  return theme("page",$output, t("Blog Admin"));
+}
+
+function blogadmin_block($op = "list", $delta = 0) {
+  if ($op == "list") {
+    $block[0]['info'] = t("Blog Admin");
+    return $block;
+  }
+
+  $block["subject"] = t("Blog Admin");
+
+  $menu = module_invoke_all("blogadmin","block");
+  /*
+  ** These should goes into the respective *_blogadmin() but leave it here
+  ** because we do not want to change too many modules
+  */
+  if (user_access("administer users"))
+    if (module_exist("user"))
+      $menu[] = l(t("users accounts"),"admin/user");
+
+  if (user_access("administer site configuration"))
+    if (module_exist("system"))
+      $menu[] = l(t("general config"),"admin/system");
+
+  if (user_access("administer site configuration"))
+    $menu[] = l(t("features options"),"blogadmin/options");
+
+  foreach ($menu as $m) {
+    $block["content"] .= "<li class=\"leaf\">".$m."</li>";
+  }
+
+  return $block;
+}
+
+?>
diff -urN drupal-4.4.1/modules/comment.module drupal4blog/modules/comment.module
--- drupal-4.4.1/modules/comment.module	Sun May  2 23:45:30 2004
+++ drupal4blog/modules/comment.module	Tue May 18 01:23:10 2004
@@ -9,6 +9,7 @@
       $output = t("
       <p>When enabled, the Drupal comment module creates a discussion board for each Drupal node. Users can post comments to discuss a forum topic, weblog post, collaborative book page, etc.</p>
       <h3>User control of comment display</h3>
+      <p>(<i>Only for Partial of Full Comment Control</i>)</p>
       <p>Attached to each comment board is a control panel for customizing the way that comments are displayed. Users can control the chronological ordering of posts (newest or oldest first) and the number of posts to display on each page. Additional settings include:</p>
       <ul>
       <li><strong>Threaded</strong> -- Displays the posts grouped according to conversations and subconversations, much like the subject view of an e-mail client.</li>
@@ -40,11 +41,13 @@
       </ul>
 
       <h3>Comment moderation</h3>
+      <p>(<i>Only for Full Comment Control</i>)</p>
       <p>On sites with active commenting from users, the administrator can turn over comment moderation to the community. </p>
       <p>With comment moderation, each comment is automatically assigned an initial rating. As users read comments, they can apply a vote which affects the comment rating. At the same time, users have an additional option in the control panel which allows them to set a threshold for the comments they wish to view. Those comments with ratings lower than the set threshold will not be shown.</p>
       <p>To enable moderation, the administrator must grant <a href=\"%permission\">moderate comments</a> permissions. Then, a number of options in <a href=\"%comment-moderation\">administer &raquo; comments &raquo; moderation</a> must be configured.</p>
 
       <h4>Moderation votes</h4>
+      <p>(<i>Only for Full Comment Control</i>)</p>
       <p>The first step is to create moderation labels which allow users to rate a comment.  Go to <a href=\"%comment-votes\">administer &raquo; comments &raquo; moderation &raquo; votes</a>. In the <em>vote</em> field, enter the textual labels which users will see when casting their votes. Some examples are</p>
       <ul>
       <li>Excellent +3</li>
@@ -58,15 +61,17 @@
       <p>Using the weight option, you can control the order in which the votes appear to users. Setting the weight heavier (positive numbers) will make the vote label appear at the bottom of the list. Lighter (a negative number) will push it to the top. To encourage positive voting, a useful order might be higher values, positive votes, at the top, with negative votes at the bottom.</p>
 
       <h4>Moderator vote/values matrix</h4>
-
+      <p>(<i>Only for Full Comment Control</i>)</p>
       <p>Next go to <a href=\"%comment-matrix\">administer &raquo; comments &raquo; moderation &raquo; matrix</a>. Enter the values for the vote labels for each permission role in the vote matrix. The values entered here will be used to create the rating for each comment.</p>
       <p>NOTE: Comment ratings are calculated by averaging user votes with the initial rating.</p>
       <h4>Creating comment thresholds</h4>
+      <p>(<i>Only for Full Comment Control</i>)</p>
       <p>In <a href=\"%comment-thresholds\">administer &raquo; comments &raquo; moderation &raquo; thresholds</a>, you'll have to create some comment thresholds to make the comment rating system useful. When comment moderation is enabled and the thresholds are created, users will find another comment control panel option for selecting their thresholds. They'll use the thresholds you enter here to filter out comments with low ratings. Consequently, you'll probably want to create more than one threshold to give users some flexibility in filtering comments.</p>
       <p>When creating the thresholds, note that the <em>Minimum score</em> is asking you for the lowest rating that a comment can have in order to be displayed.</p>
       <p>To see a common example of how thresholds work, you might visit <a href=\"%slashdot\">Slashdot</a> and view one of their comment boards associated with a story. You can reset the thresholds in their comment control panel.</p>
 
       <h4>Initial comment scores</h4>
+      <p>(<i>Only for Full Comment Control</i>)</p>
       <p>Finally, you may want to enter some <em>initial comment scores</em>. In <a href=\"%comment-initial\">administer &raquo; comments &raquo; initial comment scores</a> you can assign a beginning rating for all comments posted by a particular permission role. If you do not assign any initial scores, Drupal will assign a rating of <strong>0</strong> as the default.</p>", array("%comment-config" => url("admin/system/modules/comment"), "%site-config" => url("admin/system"), "%user-permissions" => url("admin/user/permission"), "%tracker" => url("tracker"), "%download-notify" => "http://drupal.org/project/releases", "%permission" => url("admin/user/permission"), "%comment-moderation" => url("admin/comment/moderation"), "%comment-votes" => url("admin/comment/moderation/votes"), "%comment-matrix" => url("admin/comment/moderation/matrix"), "%comment-thresholds" => url("admin/comment/moderation/filters"), "%slashdot" => " http://slashdot.org", "%comment-initial" => url("admin/comment/moderation/roles")));
       break;
     case 'admin/system/modules#description':
@@ -114,23 +119,32 @@
 }
 
 function comment_settings() {
-  $group  = form_radios(t("Default display mode"), "comment_default_mode", variable_get("comment_default_mode", 4), _comment_get_modes(), t("The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together."));
-  $group .= form_radios(t("Default display order"), "comment_default_order", variable_get("comment_default_order", 1), _comment_get_orders(), t("The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference."));
-  $group .= form_select(t("Default comments per page"), "comment_default_per_page", variable_get("comment_default_per_page", "50"), _comment_per_page(), t("Default number of comments for each page: more comments are distributed in several pages."));
-  $group .= form_radios(t("Comment controls"), "comment_controls", variable_get("comment_controls", 0), array(t("Display above the comments"), t("Display below the comments"), t("Display above and below the comments"), t("Do not display")), t("Position of the comment controls box.  The comment controls let the user change the default display mode and display order of comments."));
-  $output = form_group(t('Comment viewing options'), $group);
-
-  $group  = form_radios(t("Preview comment"), "comment_preview", variable_get("comment_preview", 1), array(t("Optional"), t("Required")), t("Must users preview comments before submitting?"));
-  $group .= form_radios(t("Location of comment submission form"), "comment_form_location", variable_get("comment_form_location", 0), array(t("Display on separate page"), t("Display below post or comments")), t("The location of the comment submission form."));
-  $output .= form_group(t('Comment posting settings'), $group);
-
-  $result = db_query("SELECT fid, filter FROM {moderation_filters} ");
-  while ($filter = db_fetch_object($result)) {
-    $thresholds[$filter->fid] = ($filter->filter);
-  }
-  if ($thresholds) {
-    $group = form_select(t("Default threshold"), "comment_default_threshold", variable_get("comment_default_threshold", 0), $thresholds, t("Thresholds are values below which comments are hidden. These thresholds are useful for busy sites which want to hide poor comments from most users."));
-    $output .= form_group(t('Comment moderation settings'), $group);
+  $group = form_radios(t("Comment Complexity"), "comment_complex", variable_get("comment_complex", 0), array(0 => t("Simple Comment Control"), 1 => t("Partial Comment Control (no moderation)"), 2 => t("Full Comment Control")),t("'Simple Comment Control' is easier to managed and sufficient for most people. 'Partial Comment Control' enables threaded comments but no moderation features. 'Full Comment Control' gives you complete control."));
+  $group .=form_radios(t("Anonymous comment options"), "comment_anon", variable_get("comment_anon", 1), array(0 => t("Anonymous users may not enter their contact info"), 1=> t("Anonymous users may leave their contact info"), 2=> t("Anonymous users <b>must</b> leave their contact info")), t("This feature is only useful if you allow anonymous user to post comments. Set this in the ") . l(t("account permission"),"admin/user/permission") . t(" configuration."));
+  $output = form_group(t('Comment control'), $group);
+
+  $group = "";
+  if (variable_get("comment_complex",0)) {
+    $group  .= form_radios(t("Default display mode"), "comment_default_mode", variable_get("comment_default_mode", 4), _comment_get_modes(), t("The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together."));
+    $group .= form_radios(t("Default display order"), "comment_default_order", variable_get("comment_default_order", 1), _comment_get_orders(), t("The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference."));
+    $group .= form_select(t("Default comments per page"), "comment_default_per_page", variable_get("comment_default_per_page", "50"), _comment_per_page(), t("Default number of comments for each page: more comments are distributed in several pages."));
+    $group .= form_radios(t("Comment controls"), "comment_controls", variable_get("comment_controls", 0), array(t("Display above the comments"), t("Display below the comments"), t("Display above and below the comments"), t("Do not display")), t("Position of the comment controls box.  The comment controls let the user change the default display mode and display order of comments."));
+    $output .= form_group(t('Comment viewing options'), $group);
+
+    $group  = form_radios(t("Preview comment"), "comment_preview", variable_get("comment_preview", 1), array(t("Optional"), t("Required")), t("Must users preview comments before submitting?"));
+    $group .= form_radios(t("Location of comment submission form"), "comment_form_location", variable_get("comment_form_location", 1), array(t("Display on separate page"), t("Display below post or comments")), t("The location of the comment submission form."));
+    $output .= form_group(t('Comment posting settings'), $group);
+  
+    if (variable_get("comment_complex",0)>1) {
+      $result = db_query("SELECT fid, filter FROM {moderation_filters} ");
+      while ($filter = db_fetch_object($result)) {
+        $thresholds[$filter->fid] = ($filter->filter);
+      }
+      if ($thresholds) {
+        $group = form_select(t("Default threshold"), "comment_default_threshold", variable_get("comment_default_threshold", 0), $thresholds, t("Thresholds are values below which comments are hidden. These thresholds are useful for busy sites which want to hide poor comments from most users."));
+        $output .= form_group(t('Comment moderation settings'), $group);
+      }
+    }
   }
 
   return $output;
@@ -187,6 +201,11 @@
 
   $comment = db_fetch_object(db_query("SELECT c.*, u.uid, u.name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status != 2", $cid));
   $comment = drupal_unpack($comment);
+
+  if (!$comment->uid && variable_get("comment_anon",1))
+      $comment->name = _comment_anon_namefix($comment,
+                       unserialize($comment->anon));
+
   if (comment_access("edit", $comment)) {
     return comment_preview(object2array($comment));
   }
@@ -205,6 +224,9 @@
     if ($pid) {
       $comment = db_fetch_object(db_query("SELECT c.*, u.uid, u.name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = 0", $pid));
       $comment = drupal_unpack($comment);
+      if (!$comment->uid && variable_get("comment_anon",1))
+        $comment->name = _comment_anon_namefix($comment,
+                           unserialize($comment->anon));
       $output .= theme("comment_view", $comment);
     }
     else if (user_access("access content")) {
@@ -250,6 +272,10 @@
   $comment->name = $user->name;
   $comment->timestamp = time();
 
+  if (!$user->uid 
+   && variable_get("comment_anon",1))
+      $comment->name = _comment_anon_namefix($comment,$edit);
+
   /*
   ** Preview the comment:
   */
@@ -260,6 +286,9 @@
   if ($edit["pid"]) {
     $comment = db_fetch_object(db_query("SELECT c.*, u.uid, u.name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = 0", $edit["pid"]));
     $comment = drupal_unpack($comment);
+    if (!$comment->uid && variable_get("comment_anon",1))
+          $comment->name = _comment_anon_namefix($comment,
+                            unserialize($comment->anon));
     $output .= theme("comment_view", $comment);
   }
   else {
@@ -428,7 +457,15 @@
 
         $edit["cid"] = db_next_id("{comments}_cid");
 
-        db_query("INSERT INTO {comments} (cid, nid, pid, uid, subject, comment, hostname, timestamp, status, score, users, thread) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%s')", $edit["cid"], $edit["nid"], $edit["pid"], $user->uid, $edit["subject"], $edit["comment"], $_SERVER['REMOTE_ADDR'], time(), $status, $score, $users, $thread);
+        $anon = "";
+        if (variable_get("comment_anon",1)) {
+            $anon = serialize(array(
+                'anon_name' => trim(strip_tags($edit['anon_name'])),
+                'anon_mail' => trim(strip_tags($edit['anon_mail'])),
+                'anon_url' => trim(strip_tags($edit['anon_url']))));
+        }
+
+        db_query("INSERT INTO {comments} (cid, nid, pid, uid, subject, comment, hostname, timestamp, status, score, users, anon, thread) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%s', '%s')", $edit["cid"], $edit["nid"], $edit["pid"], $user->uid, $edit["subject"], $edit["comment"], $_SERVER['REMOTE_ADDR'], time(), $status, $score, $users, $anon, $thread);
 
         /*
         ** Tell the other modules a new comment has been submitted:
@@ -532,6 +569,7 @@
 
     if (empty($mode)) {
       $mode = $user->mode ? $user->mode : ($_SESSION["comment_mode"] ? $_SESSION["comment_mode"] : variable_get("comment_default_mode", 4));
+      if (variable_get("comment_complex",0) == 0) $mode = 2;
     }
 
     if (empty($order)) {
@@ -561,6 +599,9 @@
       $result = db_query("SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = 0 GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users", $cid);
 
       if ($comment = db_fetch_object($result)) {
+        if (!$comment->uid && variable_get("comment_anon",1))
+            $comment->name = _comment_anon_namefix($comment,
+                            unserialize($comment->anon));
         $output .= theme("comment_view", $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1)));
       }
 
@@ -575,7 +616,12 @@
       ** Multiple comments view
       */
 
-      $query .= "SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users, c.thread FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = '". check_query($nid) ."' AND c.status = 0";
+      $query .= "SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.status, c.anon, c.users, c.thread FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = '". check_query($nid);
+      
+      if (!user_access("administer comments"))
+          $query .= "' AND c.status = 0";
+      else
+          $query .= "' AND (c.status = 0 OR c.status = 1)";
 
       $query .= " GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users, c.thread";
 
@@ -671,7 +717,7 @@
       */
 
       $result = pager_query($query, $comments_per_page, 0, "SELECT COUNT(*) FROM {comments} WHERE nid = '". check_query($nid) ."'");
-      if (db_num_rows($result) && (variable_get("comment_controls", 0) == 0 || variable_get("comment_controls", 0) == 2)) {
+      if (db_num_rows($result) && ((variable_get("comment_controls", 0) == 0 && variable_get("comment_complex",0)) || variable_get("comment_controls", 0) == 2)) {
         $output .= "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
         $output .= theme("comment_controls", $threshold, $mode, $order, $comments_per_page);
         $output .= form_hidden("nid", $nid);
@@ -683,6 +729,10 @@
 
       while ($comment = db_fetch_object($result)) {
         $comment = drupal_unpack($comment);
+        if (!$comment->uid && variable_get("comment_anon",1))
+            $comment->name = _comment_anon_namefix($comment,
+                                unserialize($comment->anon));
+
         $comment->depth = count(explode(".", $comment->thread)) - 1;
 
         if ($mode == 1) {
@@ -693,7 +743,7 @@
         }
         else if ($mode == 3) {
           $output .= theme("comment_thread_min", $comment, $threshold_min);
-        }
+    }
         else if ($mode == 4) {
           $output .= theme("comment_thread_max", $comment, $threshold_min);
         }
@@ -725,7 +775,7 @@
     ** If enabled, show new comment form
     */
 
-    if (user_access("post comments") && node_comment_mode($nid) == 2 && variable_get("comment_form_location", 0)) {
+    if (user_access("post comments") && node_comment_mode($nid) == 2 && variable_get("comment_form_location", 1)) {
       $output .= theme("comment_form", array("nid" => $nid), t("Post new comment"));
     }
   }
@@ -733,7 +783,13 @@
 }
 
 function comment_perm() {
-  return array("access comments", "post comments", "administer comments", "moderate comments", "post comments without approval", "administer moderation");
+  switch (variable_get("comment_complex",0)) {
+      case 0:
+      case 1:
+        return array("access comments", "post comments", "administer comments", "post comments without approval");
+      case 2:
+        return array("access comments", "post comments", "administer comments", "moderate comments", "post comments without approval", "administer moderation");
+  }
 }
 
 function comment_link($type, $node = 0, $main = 0) {
@@ -750,13 +806,21 @@
       if (user_access("access comments")) {
         $all = comment_num_all($node->nid);
         $new = comment_num_new($node->nid);
+        $unp = comment_num_unpublish($node->nid);
 
         if ($all) {
-          $links[] = l(format_plural($all, "1 comment", "%count comments"), "node/view/$node->nid", array("title" => t("Jump to the first comment of this posting.")), NULL, "comment");
+          if ($new && $unp)
+              $title = sprintf("%d new and %d unpublish comments", $new, $unp);
+          else if ($new)
+              $title .= format_plural($new, "1 new comment", 
+                            "%count new comments");
+          else if ($unp)
+              $title .= format_plural($unp, "1 unpublish comment", 
+                            "%count unpublish comments");
+          else
+              $title = "Jump to the first comment of this posting.";
 
-          if ($new) {
-            $links[] = l(format_plural($new, "1 new comment", "%count new comments"), "node/view/$node->nid", array("title" => t("Jump to the first new comment of this posting.")), NULL, "new");
-          }
+          $links[] = l(format_plural($all, "1 comment", "%count comments"), "node/view/$node->nid", array("title" => t($title)), NULL, "comment");
         }
         else {
           if ($node->comment == 2) {
@@ -806,7 +870,8 @@
       }
 
       // comment settings:
-      if (user_access("administer moderation")) {
+      if (user_access("administer moderation") 
+      && (variable_get("comment_complex",0)>1)) {
         menu("admin/comment/moderation", t("moderation"), "comment_admin", 3);
         menu("admin/comment/moderation/votes", t("votes"), "comment_admin");
         menu("admin/comment/moderation/matrix", t("matrix"), "comment_admin");
@@ -901,6 +966,10 @@
   $comment = drupal_unpack($comment);
 
   if ($comment) {
+    if (!$comment->uid && variable_get("comment_anon",1))
+        $comment->name = _comment_anon_namefix($comment,
+                            unserialize($comment->anon));
+
     $form .= form_item(t("Author"), format_name($comment));
     $form .= form_textfield(t("Subject"), "subject", $comment->subject, 70, 128);
     $form .= form_textarea(t("Comment"), "comment", $comment->comment, 70, 15, filter_tips_short());
@@ -927,6 +996,10 @@
 function comment_delete($cid, $confirmed = 0) {
   $comment = db_fetch_object(db_query("SELECT c.*, u.name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d", $cid));
 
+  if (!$comment->uid && variable_get("comment_anon",1))
+      $comment->name = _comment_anon_namefix($comment,
+                       unserialize($comment->anon));
+
   if ($comment->cid) {
     if ($confirmed) {
       drupal_set_message(t("the comment and all its replies have been deleted."));
@@ -963,6 +1036,13 @@
 }
 
 function comment_save($id, $edit) {
+  $anon = "";
+  if (variable_get("comment_anon",1)) {
+    $anon = serialize(array(
+        'anon_name' => trim(strip_tags($edit['anon_name'])),
+        'anon_mail' => trim(strip_tags($edit['anon_mail'])),
+        'anon_url' => trim(strip_tags($edit['anon_url']))));
+  }
   db_query("UPDATE {comments} SET subject = '%s', comment = '%s', status = %d WHERE cid = %d", $edit["subject"], $edit["comment"], $edit["status"], $id);
   watchdog("special", "comment: modified '". $edit["subject"] ."'");
   drupal_set_message(t("the comment has been saved."));
@@ -983,6 +1063,10 @@
   $result = pager_query($sql,  50);
 
   while ($comment = db_fetch_object($result)) {
+    if (!$comment->uid && variable_get("comment_anon",1))
+        $comment->name = _comment_anon_namefix($comment,
+                            unserialize($comment->anon));
+
     $rows[] = array(l($comment->subject, "node/view/$comment->nid/$comment->cid", array("title" => htmlspecialchars(substr($comment->comment, 0, 128))), NULL, "comment-$comment->cid") ." ". (node_is_new($comment->nid, $comment->timestamp) ? theme("mark") : ""), format_name($comment), ($comment->status == 0 ? t("published") : t("not published")) ."</td><td>". format_date($comment->timestamp, "small") ."</td><td>". l(t("edit comment"), "admin/comment/edit/$comment->cid"), l(t("delete comment"), "admin/comment/delete/$comment->cid"));
   }
 
@@ -1186,19 +1270,22 @@
     case t("Add new vote"):
     case t("Delete vote"):
     case t("Save vote"):
-      if (user_access("administer moderation")) {
+      if (user_access("administer moderation")
+      && (variable_get("comment_complex",0)>1)) {
         $output = comment_mod_votes($edit);
       }
       break;
     case "roles":
     case t("Save scores"):
-      if (user_access("administer moderation")) {
+      if (user_access("administer moderation")
+      && (variable_get("comment_complex",0)>1)) {
         $output = comment_mod_roles($edit);
       }
       break;
     case "matrix":
     case t("Submit votes"):
-      if (user_access("administer moderation")) {
+      if (user_access("administer moderation")
+      && (variable_get("comment_complex",0)>1)) {
         $output = comment_mod_matrix($edit);
       }
       break;
@@ -1206,7 +1293,8 @@
     case t("Add new threshold"):
     case t("Delete threshold"):
     case t("Save threshold"):
-      if (user_access("administer moderation")) {
+      if (user_access("administer moderation")
+      && (variable_get("comment_complex",0)>1)) {
         $output = comment_mod_filters($edit);
       }
       break;
@@ -1220,6 +1308,16 @@
       $output  = comment_save(check_query(arg(3)), $edit);
       $output .= comment_admin_overview(0);
       break;
+    case "unpublish":
+      _comment_unpublish(check_query(arg(3)));
+      drupal_goto(comment_referer_load());
+      break;
+
+    case "publish":
+      _comment_publish(check_query(arg(3)));
+      drupal_goto(comment_referer_load());
+      break;
+
     default:
       if (arg(3) == 1) {
         $output = comment_admin_overview(1);
@@ -1241,8 +1339,18 @@
 
   $form .= "<a id=\"comment\"></a>\n";
 
-  // name field:
-  $form .= form_item(t("Your name"), format_name($user));
+  if ($user->name || variable_get("comment_anon",1) == 0) {
+    // name field:
+    $form .= form_item(t("Your name"), format_name($user));
+  } else {
+    $form .= form_textfield(t("Name"), "anon_name", $edit['anon_name'], 30, 64);
+    $form .= form_textfield(t("E-mail Address"), "anon_mail", 
+        $edit['anon_mail'], 30, 64, 
+        variable_get("comment_anon",1) == 2 ? t("You must leave your name and email to post comments.") : "");
+    $form .= form_textfield(t("Homepage"), "anon_url", 
+        $edit['anon_url'], 30, 64, 
+        t("e.g. http://www.example.com/ - Your E-mail will not be display if you entered your homepage."));
+  }
 
   // subject field:
   $form .= form_textfield(t("Subject"), "subject", $edit["subject"], 50, 64);
@@ -1356,8 +1464,21 @@
   if ($op == "reply") {
     // preview comment:
     $output .= "&nbsp;";
+    return $output;
+  }
+
+  /* simple or partial comment control */
+  if (user_access("administer comments") && variable_get("comment_complex", 0) <= 1) {
+    if ($comment->status == 0) 
+        $output .= l(t("unpublish comment"),
+            "admin/comment/unpublish/".$comment->cid);
+    else if ($comment->status == 1)
+        $output .= l(t("publish comment"),
+            "admin/comment/publish/".$comment->cid);
+    return $output;
   }
-  else if ((comment_user_can_moderate($node)) && $user->uid != $comment->uid && !(comment_already_moderated($user->uid, $comment->users))) {
+
+  if ((comment_user_can_moderate($node)) && $user->uid != $comment->uid && !(comment_already_moderated($user->uid, $comment->users))) {
     // comment hasn't been moderated yet:
 
     if (!isset($votes)) {
@@ -1383,9 +1504,10 @@
     }
 
     $output .= "<select name=\"moderation[$comment->cid]\">$options</select>\n";
+    return $output;
   }
 
-  return $output;
+  return "";
 }
 
 function theme_comment($comment, $links = 0) {
@@ -1483,6 +1605,9 @@
         if ($vote) {
           $comment = db_fetch_object(db_query("SELECT * FROM {comments} WHERE cid = %d", $cid));
           $users = unserialize($comment->users);
+          if (!$comment->uid && variable_get("comment_anon",1))
+            $comment->name = _comment_anon_namefix($comment,
+                                unserialize($comment->anon));
           if ($user->uid != $comment->uid && !(comment_already_moderated($user->uid, $comment->users))) {
             $users[$user->uid] = $vote;
             $tot_score = 0;
@@ -1528,11 +1653,19 @@
   static $cache;
 
   if (!isset($cache[$nid])) {
-    $cache[$nid] = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = 0", $nid));
+    if (user_access("administer comments")) {
+        $cache[$nid] = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE nid = %d", $nid));
+    } else {
+        $cache[$nid] = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = 0", $nid));
+    }
   }
   return $cache[$nid];
 }
 
+function comment_num_unpublish($nid) {
+  return db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = 1", $nid));
+}
+
 function comment_num_replies($pid) {
   static $cache;
 
@@ -1567,7 +1700,11 @@
     ** Use the timestamp to retrieve the number of new comments
     */
 
-    $result = db_result(db_query("SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = 0", $nid, $timestamp));
+    if (user_access("administer comments")) {
+        $result = db_result(db_query("SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d", $nid, $timestamp));
+    } else {
+        $result = db_result(db_query("SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = 0", $nid, $timestamp));
+    }
 
     return $result;
   }
@@ -1579,7 +1716,9 @@
 
 function comment_user_can_moderate($node) {
   global $user;
-  return (user_access("moderate comments"));
+  return (user_access("moderate comments") 
+      && (variable_get("comment_complex",0)>1));
+
   // TODO: || (($user->uid == $node->uid) && user_access("moderate comments in owned node")));
 }
 
@@ -1688,6 +1827,59 @@
 
 function _comment_per_page() {
   return drupal_map_assoc(array(10, 30, 50, 70, 90));
+}
+
+/*
+ * Should go into theme.inc?
+ */
+function theme_notmember() {
+    return ' <span class="marker">(non-member)</span>';
+}
+
+function _comment_anon_namefix($comment,$anon) {
+    $anon_name = trim(strip_tags($anon['anon_name']));
+    $anon_mail = trim(strip_tags($anon['anon_mail']));
+    $anon_url = trim(strip_tags($anon['anon_url']));
+
+    if (strlen($anon_name)<=0) return $comment->name;
+
+    if (strlen($anon_url)>0
+    && preg_match(
+        "/^(http|https):\/\/[a-zA-Z0-9\-\.\/\&\/?\=]+$/", $anon_url)) {
+        return "<a href=\"$anon_url\">$anon_name</a> " . theme('notmember');
+    } else if (strlen($anon_mail)>0
+    && preg_match("/^\S+@[a-zA-Z0-9\-\.]+$/", $anon_mail)) {
+        return "<a href=\"mailto:$anon_mail\">$anon_name</a> " . theme('notmember');
+    }
+
+    return $anon_name ." ". theme('notmember');
+}
+
+function _comment_publish($cid) {
+  if (!user_access("administer comments")) return;
+  $comment = db_fetch_object(db_query("SELECT * FROM {comments} WHERE cid = %d", $cid));
+  if ($comment) {
+    db_query("UPDATE {comments} SET status = %d WHERE cid = %d", 0, $cid);
+    watchdog("special", "comment: published '".$comment->subject ."'");
+    drupal_set_message(t("Comment '".$comment->subject."' has been publish."));
+  }
+}
+
+function _comment_unpublish($cid) {
+  if (!user_access("administer comments")) return;
+  $comment = db_fetch_object(db_query("SELECT * FROM {comments} WHERE cid = %d", $cid));
+  if ($comment) {
+    db_query("UPDATE {comments} SET status = %d WHERE cid = %d", 1, $cid);
+    watchdog("special", "comment: unpublished '".$comment->subject ."'");
+    drupal_set_message(t("Comment '".$comment->subject."' has been unpublish."));
+  }
+}
+
+function comment_blogadmin($type) {
+  if ($type == "options") {
+    if (user_access("administer site configuration"))
+      return array(l(t("Comment options"),"admin/system/modules/comment") => t("Configure comments options."));
+  } 
 }
 
 ?>
diff -urN drupal-4.4.1/modules/ping.module drupal4blog/modules/ping.module
--- drupal-4.4.1/modules/ping.module	Sun May  2 23:45:30 2004
+++ drupal4blog/modules/ping.module	Tue May 18 01:23:10 2004
@@ -17,17 +17,39 @@
     case 'admin/system/modules#description':
       $output = t("Alerts other site(s) that your site has been updated.");
       break;
+
+    case 'admin/system/modules/ping':
+      $output = t("
+        <p>There are three different ways to notify different search engine
+        or websphere trackers. If you don't know what these means, then
+        just leave it as-is.</p>
+        <p>Pings are send out once every few hours, depending how frequent
+        you set your cron.php (see Section 6 on CRON TASKS in INSTALL).
+        Pings <b>will not</b> be send unless you configure your the name
+        and 'slogan' of your site. See configuration.</p>", 
+            array("configuration" => l(t("configuration"),"admin/system")));
   }
 
   return $output;
 }
 
+function ping_settings() {
+    $output = "";
+    $output .= form_textarea(t("Sites to alert (ping)"), "ping_ping", variable_get("ping_ping", "http://rpc.weblogs.com/RPC2"), 70, 4, t("Send weblogUpdates.ping to these sites"));
+    $output .= form_textarea(t("Sites to alert (advance ping)"), "ping_extping", variable_get("ping_extping", "http://ping.blo.gs/\nhttp://rpc.technorati.com/rpc/ping/"), 70, 4, t("Send weblogUpdates.extendedPing to these sites"));
+    $output .= form_textarea(t("Sites to alert (rss update)"), "ping_rss", variable_get("ping_rss", "http://rssrpc.weblogs.com/RPC2"), 70, 4, t("Send rssUpdate to these sites"));
+    return $output;
+}
+
 function ping_cron() {
   global $base_url;
 
   if (variable_get("site_name", 0) && variable_get("site_slogan", 0)) {
     if (db_num_rows(db_query("SELECT nid FROM {node} WHERE status = 1 AND moderate = 0 AND (created > '". variable_get("ping_cron_last", time()) ."' OR changed > '". variable_get("ping_cron_last", time()) ."')"), 1)) {
-      _ping_notify(variable_get("site_name", "") ." - ". variable_get("site_slogan", ""), $base_url);
+      $site = variable_get("site_name","drupal");
+      if (variable_get("site_slogan", "")) 
+          $site .= " - " . variable_get("site_slogon", "");
+      _ping_notify($site, $base_url);
     }
 
     variable_set("ping_cron_last", time());
@@ -41,39 +63,68 @@
 function ping_ping($name = "", $url = "") {
   $feed = url("node/feed");
 
-  $client = new xmlrpc_client("/RPC2", "rpc.weblogs.com", 80);
+  $urls = preg_split("/\s+/",
+    variable_get("ping_ping", "http://rpc.weblogs.com/RPC2"));
+  foreach ($urls as $pingurl) {
+      $purl = parse_url($pingurl);
+      $path = $purl['path'];
+      if (strlen($purl['query'])>0)     $path .= "?".$purl['query'];
+      if (strlen($purl['fragment'])>0)   $path .= "#".$purl['fragment'];
+
+      $client = new xmlrpc_client($path,$purl['host'],$purl['port']);
+
+      $message = new xmlrpcmsg("weblogUpdates.ping", array(new xmlrpcval($name), new xmlrpcval($url)));
 
-  $message = new xmlrpcmsg("weblogUpdates.ping", array(new xmlrpcval($name), new xmlrpcval($url)));
+      $result = $client->send($message);
 
-  $result = $client->send($message);
+      if (!$result || $result->faultCode()) {
+        watchdog("error", "weblogUpdates.ping: failed to notify ".$pingurl);
+      } 
 
-  if (!$result || $result->faultCode()) {
-    watchdog("error", "failed to notify 'weblogs.com' (site)");
+      unset($client);
   }
 
-  unset($client);
+  $urls = preg_split("/\s+/",
+    variable_get("ping_extping", "http://ping.blo.gs/\nhttp://rpc.technorati.com/rpc/ping/"));
+  foreach ($urls as $pingurl) {
+      $purl = parse_url($pingurl);
+      $path = $purl['path'];
+      if (strlen($purl['query'])>0)     $path .= "?".$purl['query'];
+      if (strlen($purl['fragment'])>0)   $path .= "#".$purl['fragment'];
 
-  $client = new xmlrpc_client("/RPC2", "rssrpc.weblogs.com", 80);
+      $client = new xmlrpc_client($path,$purl['host'],$purl['port']);
 
-  $message = new xmlrpcmsg("rssUpdate", array(new xmlrpcval($name), new xmlrpcval($feed)));
+      $message = new xmlrpcmsg("weblogUpdates.extendedPing", array(new xmlrpcval($name), new xmlrpcval($url), new xmlrpcval($url), new xmlrpcval($feed)));
 
-  $result = $client->send($message);
+      $result = $client->send($message,0,$purl['scheme']);
 
-  if (!$result || $result->faultCode()) {
-    watchdog("error", "failed to notify 'weblogs.com' (RSS)");
+      if (!$result || $result->faultCode()) {
+        watchdog("error", "weblogUpdates.extendedPing: failed to notify ".$pingurl);
+      } 
+
+      unset($client);
   }
 
-  unset($client);
+  $urls = preg_split("/\s+/",
+    variable_get("ping_rss", "http://rssrpc.weblogs.com/RPC2"));
+  foreach ($urls as $pingurl) {
+      $purl = parse_url($pingurl);
+      $path = $purl['path'];
+      if (strlen($purl['query'])>0)     $path .= "?".$purl['query'];
+      if (strlen($purl['fragment'])>0)   $path .= "#".$purl['fragment'];
 
-  $client = new xmlrpc_client("/", "ping.blo.gs", 80);
+      $client = new xmlrpc_client($path,$purl['host'],$purl['port']);
 
-  $message = new xmlrpcmsg("weblogUpdates.extendedPing", array(new xmlrpcval($name), new xmlrpcval($url), new xmlrpcval($url), new xmlrpcval($feed)));
+      $message = new xmlrpcmsg("rssUpdate", array(new xmlrpcval($name), new xmlrpcval($feed)));
 
-  $result = $client->send($message);
+      $result = $client->send($message,0,$purl['scheme']);
 
-  if (!$result || $result->faultCode()) {
-    watchdog("error", "failed to notify 'blo.gs' ");
-  }
+      if (!$result || $result->faultCode()) {
+        watchdog("error", "rssUpdate: failed to notify ".$pingurl);
+      } 
 
+      unset($client);
+  }
 }
+
 ?>
diff -urN drupal-4.4.1/modules/taxonomy.module drupal4blog/modules/taxonomy.module
--- drupal-4.4.1/modules/taxonomy.module	Sun May  2 23:45:30 2004
+++ drupal4blog/modules/taxonomy.module	Tue May 18 01:23:10 2004
@@ -17,6 +17,11 @@
   }
 }
 
+function taxonomy_settings() {
+  $output = form_radios(t("Taxonomy Complexity"), "taxonomy_complex", variable_get("taxonomy_complex", 0), array(0 => t("Simple Taxonomy"), 1 => t("Nested Taxonomy"), 2 => t("Full Taxonomy Control")),t("Taxonomy is just a fancy word for Category. You can attach 'taxonomy' to your entries which will specify their categories. 'Simple Taxonomy' is easier to managed and sufficient for most people. 'Nested Taxonomy' enables hierarchical categories. 'Full Taxonomy Control' gives you complete control."));
+  return $output;
+}
+
 function taxonomy_perm() {
   return array("administer taxonomy");
 }
@@ -149,30 +154,34 @@
   $form = form_textfield(t("Term name"), "name", $edit["name"], 50, 64, t("Required") .". ". t("The name for this term.  Example: 'Linux'."));
   $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") .". ". t("A description of the term."));
 
-  if ($vocabulary->hierarchy) {
-    $parent = array_keys(taxonomy_get_parents($edit["tid"]));
-    $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]);
-
-    // you can't be son of yourself nor of your children
-    foreach ($children as $child) {
-      $exclude[] = $child->tid;
+  if (variable_get("taxonomy_complex",0)>0) {
+    if ($vocabulary->hierarchy) {
+      $parent = array_keys(taxonomy_get_parents($edit["tid"]));
+      $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]);
+  
+      // you can't be son of yourself nor of your children
+      foreach ($children as $child) {
+        $exclude[] = $child->tid;
+      }
+      $exclude[] = $edit["tid"];
+  
+      if ($vocabulary->hierarchy == 1) {
+        $form .= _taxonomy_term_select(t("Parent"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent term"), "admin/taxonomy/help", NULL, NULL, "parent") .". Specify this to define sub-term.", 0, "<". t("root") .">", $exclude);
+      }
+      elseif ($vocabulary->hierarchy == 2) {
+        $form .= _taxonomy_term_select(t("Parents"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent terms"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 1, "<". t("root") .">", $exclude);
+      }
+    }
+  
+    if (variable_get("taxonomy_complex",0)>1) {
+      if ($vocabulary->relations) {
+        $form .= _taxonomy_term_select(t("Related terms"), "relations", array_keys(taxonomy_get_related($edit["tid"])), $vocabulary_id, t("Optional") .". ", 1, "<". t("none") .">", array($edit["tid"]));
+      }
+    
+      $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t("<a href=\"%help-url\">Synonyms</a> of this term, one synonym per line.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "synonyms"))));
+      $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top."));
     }
-    $exclude[] = $edit["tid"];
-
-    if ($vocabulary->hierarchy == 1) {
-      $form .= _taxonomy_term_select(t("Parent"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent term"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 0, "<". t("root") .">", $exclude);
-    }
-    elseif ($vocabulary->hierarchy == 2) {
-      $form .= _taxonomy_term_select(t("Parents"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent terms"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 1, "<". t("root") .">", $exclude);
-    }
-  }
-
-  if ($vocabulary->relations) {
-    $form .= _taxonomy_term_select(t("Related terms"), "relations", array_keys(taxonomy_get_related($edit["tid"])), $vocabulary_id, t("Optional") .". ", 1, "<". t("none") .">", array($edit["tid"]));
   }
-
-  $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t("<a href=\"%help-url\">Synonyms</a> of this term, one synonym per line.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "synonyms"))));
-  $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top."));
   $form .= form_hidden("vid", $vocabulary->vid);
   $form .= form_submit(t("Submit"));
 
@@ -186,21 +195,27 @@
 
 function taxonomy_save_term($edit) {
   if ($edit["tid"] && $edit["name"]) {
-    $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]);
-
-    db_query("UPDATE {term_data} SET ". _prepare_update($data) ." WHERE tid = %d", $edit["tid"]);
-    module_invoke_all("taxonomy", "update", "term", $edit);
-    $message = t("the term '%a' has been updated.", array("%a" => $edit["name"]));
+    if (_taxonomy_dup_term($edit["tid"],$edit["name"])) {
+      $message = t("the term '%a' already exist.",array("%a" => $edit["name"]));
+    } else {
+      $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]);
+      db_query("UPDATE {term_data} SET ". _prepare_update($data) ." WHERE tid = %d", $edit["tid"]);
+      module_invoke_all("taxonomy", "update", "term", $edit);
+      $message = t("the term '%a' has been updated.", array("%a" => $edit["name"]));
+    }
   }
   else if ($edit["tid"]) {
-    return taxonomy_del_term($edit["tid"]);
-  }
-  else {
-    $edit["tid"] = db_next_id("{term_data}_tid");
-    $data = array("tid" => $edit["tid"], "name" => $edit["name"], "description" => $edit["description"], "vid" => $edit["vid"], "weight" => $edit["weight"]);
-    db_query("INSERT INTO {term_data} ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2));
-    module_invoke_all("taxonomy", "insert", "term", $edit);
-    $message = t("created new term '%name'.", array("%name" => $edit["name"]));
+    $message = t("Please click 'Delete' if you wish to delete the term.");
+  } else {
+    if (_taxonomy_dup_term($edit["tid"],$edit["name"])) {
+      $message = t("the term '%name' already exist.", array("%name" => $edit["name"]));
+    } else {
+      $edit["tid"] = db_next_id("{term_data}_tid");
+      $data = array("tid" => $edit["tid"], "name" => $edit["name"], "description" => $edit["description"], "vid" => $edit["vid"], "weight" => $edit["weight"]);
+      db_query("INSERT INTO {term_data} ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2));
+      module_invoke_all("taxonomy", "insert", "term", $edit);
+      $message = t("created new term '%name'.", array("%name" => $edit["name"]));
+    }
   }
 
   // relations (seem very powerful, but I have to understand it completely)
@@ -255,6 +270,7 @@
 
   cache_clear_all();
 
+  drupal_set_message(t("deleted term '%name'.", array("%name" => $term->name)));
   return t("deleted term '%name'.", array("%name" => $term->name));
 }
 
@@ -271,6 +287,28 @@
 }
 
 function taxonomy_overview() {
+  if (variable_get("taxonomy_complex",0)<=1) {
+    $vocabularies = taxonomy_get_vocabulary_by_name("Category");
+    if (!$vocabularies[0]) {
+      $vid = db_next_id("{vocabulary}_vid");
+      db_query("INSERT INTO {vocabulary} VALUES (%d, '%s', '%s', %d, %d, %d, %d, '%s', %d)", $vid, "Category", "Categories for Blog Entries", 0, 1, 1, 0, 'blog', 0);
+      $vocabularies = taxonomy_get_vocabulary_by_name("Category");
+    }
+    $vid = $vocabularies[0]->vid;
+
+    $headers = array(t("name"), t("description"));
+
+    $tree = taxonomy_get_tree($vid);
+    if ($tree) {
+      unset($data);
+      foreach($tree as $term) {
+        $rows[] = array(l(_taxonomy_depth($term->depth)." ".$term->name, "admin/taxonomy/edit/term/$term->tid") , $term->description);
+      }
+    }
+    $rows[] = array(array("data" => l(t("add category"), "admin/taxonomy/add/term/$vid"), "colspan" => 2));;
+
+    return theme("table",$headers,$rows);
+  }
 
   $output .= "<h3>". t("Vocabularies overview") ."</h3>";
 
@@ -817,7 +855,7 @@
         taxonomy_save_term($edit);
         if (!$edit["tid"]) {
           // if INSERT show form again
-          $output .= taxonomy_form_term();
+          $output .= taxonomy_overview(); // taxonomy_form_term();
           break;
         }
         // else (UPDATE or DELETE) fall through
@@ -882,4 +920,26 @@
 
   return $output;
 }
+
+function taxonomy_blogadmin($type) {
+  $list = array();
+
+  if ($type == "block") {
+    if (user_access("administer taxonomy"))
+      $list[] = l(t("categories"), "admin/taxonomy");
+  } else if ($type == "options") {
+    if (user_access("administer site configuration")) {
+      $list[l(t("Category options"),"admin/system/modules/taxonomy")] = t("Configure category/taxonomy options");
+    }
+  }
+
+  return $list;
+}
+
+function _taxonomy_dup_term($tid,$name) {
+  $term = db_fetch_object(db_query("SELECT * FROM {term_data} WHERE tid=%d",$tid));
+  $result = db_fetch_object(db_query("SELECT * FROM {term_data} WHERE LOWER(name)=LOWER('%s') AND vid=%d",trim($name),$term->vid));
+  return $result;
+}
+
 ?>
diff -urN drupal-4.4.1/modules/trackback.module drupal4blog/modules/trackback.module
--- drupal-4.4.1/modules/trackback.module	Fri May 14 18:55:43 2004
+++ drupal4blog/modules/trackback.module	Tue May 18 01:23:10 2004
@@ -5,9 +5,23 @@
   switch ($section) {
     case 'admin/system/modules#description':
       return t("Allow for sending and receiving TrackBacks, which is a way for sites to notify another that they have commented on a post.");
+    case 'admin/system/modules/trackback':
+      return t("Trackback can be attached to any node and is treated like comments for all intent and purpose.");
   }
 }
 
+function trackback_settings() {
+    $output = "";
+
+    $array_moderate = array(0 => t("No"), 1 => t("Yes"));
+    $output .= form_radios(t("Display Trackback only after approval"), "trackback_moderation", variable_get("trackback_moderation", 0), $array_moderate, t("If yes, all trackback must be moderated before it can be seen by others."));
+
+    $array_moderate = array(0 => t("No"), 1 => t("Yes"));
+    $output .= form_radios(t("Trackback autodiscovery"), "trackback_autodiscovery", variable_get("trackback_autodiscovery", 1), $array_moderate, t("If yes, any external links will be extracted and the appropriate sites will be sent a Trackback ping. Take note it might slowdown your posting esp. if there is a lot of external links."));
+
+    return $output;
+}
+
 function trackback_send($node) {
   $params = array(
     "title" => $node->title,
@@ -20,12 +34,56 @@
     $str[] = "$key=". urlencode($value);
   }
 
-  return drupal_http(
-    $node->tb_url,
-    $headers = array("Content-Type" => "application/x-www-form-urlencoded"),
-    "POST",
-    implode("&", $str)
-  );
+  $node->toping = ""; # Start from scratch
+
+  $tb_urls = $node->tb_url;
+  if (variable_get("trackback_autodiscovery",1)) {
+    $text = $node->body; 
+    if ($node->type == 'blog')
+      $text .= " ".$node->extended." ".$node->excerpt;
+    preg_match_all("|http://[\w\.\-\+\&\+\=\/\#\%]+|",$text,$murl);
+    $links = array_unique($murl[0]);
+    foreach ($links as $url) {
+      $result = drupal_http($url);
+      $result->data = preg_replace("/[\n\r]/"," ",$result->data);
+      $tb = preg_replace("/.*<rdf\:RDF.*trackback\:ping\=\"([^\"]+)\".*<\/rdf\:RDF>.*/","\\1",$result->data);
+      $tb_urls .= " ".$tb;
+    }
+  }
+
+  $urls = preg_split("/\s+/",$tb_urls);
+  foreach($urls as $url) {
+    # No need to ping empty URL
+    if (strlen($url)<=0) continue;
+
+    # Do not ping those already ping'ed unless explicitly specified 
+    if (strstr($node->pinged,$url) && !strstr($node->tb_url,$url)) continue;
+
+    $result = drupal_http(
+        $url,
+        $headers = array("Content-Type" => "application/x-www-form-urlencoded"),
+        "POST",
+        implode("&", $str)
+    );
+
+    if (strlen(trim($result->error))>0) {
+      drupal_set_message("Error! Unable to send Trackback ping to ".$url);
+      if (!strstr($node->toping,$url))
+        $node->toping .= "\n".$url; $node->toping = trim($node->toping);
+    } else {
+      drupal_set_message("Success! Trackback ping send to ".$url);
+      if (!strstr($node->pinged,$url))
+        $node->pinged .= "\n".$url; $node->pinged = trim($node->pinged);
+    }
+  }
+
+  $c = db_result(
+    db_query("SELECT COUNT(nid) FROM {tb} WHERE nid = %d", $node->nid));
+
+  if ($c>0) 
+      trackback_update($node);
+  else 
+      trackback_insert($node);
 }
 
 function trackback_receive($node) {
@@ -40,10 +98,13 @@
     $subject = ($_REQUEST["title"]) ? $_REQUEST["title"] : $trackback->url;
     $comment = "<strong>". t("TrackBack from %url", array("%url" => "<a href=\"$trackback->url\">$trackback->name</a>")) .":</strong><br />";
     $comment .= "<blockquote>$trackback->excerpt</blockquote>";
+    $anon = serialize(array(
+            'anon_name' => trim(strip_tags($trackback->name)),
+            'anon_url' => trim(strip_tags($trackback->url))));
     $cid = db_next_id("comments_cid");
     $thread = rtrim(db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE nid = %d", $node->nid)), "/") + 1;
-    db_query("INSERT INTO comments (cid, nid, pid, uid, subject, comment, hostname, timestamp, status, score, users, thread) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%d/')",
-             $cid, $node->nid, 0, 0, $subject, $comment, getenv("REMOTE_ADDR"), time(), 0, 0, '', $thread);
+    db_query("INSERT INTO comments (cid, nid, pid, uid, subject, comment, hostname, timestamp, status, score, anon, thread) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%s')",
+             $cid, $node->nid, 0, 0, $subject, $comment, getenv("REMOTE_ADDR"), time(), variable_get("trackback_moderation", 0), 0, $anon, $thread);
     watchdog("special", t("trackback: added '%subject'", array("%subject" => $subject)), l(t("view comment"), "node/view/". $node->nid ."#". $cid));
     $error = 0;
   }
@@ -63,36 +124,91 @@
 }
 
 function trackback_page() {
-  if (is_numeric(arg(1)) && $node = node_load(array("nid" => arg(1)))) {
-    header("Content-Type: text/xml");
-    print trackback_receive($node);
-  }
-  else {
-    drupal_goto();
-  }
+    global $base_url;
+
+    if (arg(1) == "url" && is_numeric(arg(2)) 
+        && $node = node_load(array("nid" => arg(2)))) {
+        $output = t("<p>The Trackback URL for node is:<br/><blockquote>url</blockquote></p>",
+                    array("node" => l("'$node->title'","node/view/$node->nid"),
+                          "url" => l($base_url . "/" . url("trackback/$node->nid"),
+                            "trackback/$node->nid")));
+
+        if (user_access("administer nodes")) {
+          $node = trackback_load_node($node);
+          $urls = preg_split("/\s+/",$node->pinged);
+          $head = 0;
+          foreach ($urls as $url) {
+            $url = strip_tags($url);
+            if (strlen(trim($url))<=0) continue;
+            if ($head == 0) {
+              $output .=  "<p>".
+                t("Trackback pings have been sent to the following URLs:");
+              $head = 1;
+            }
+            $output .= "<li>$url</li>\n";
+          }
+          if ($head) $output .= "</p>";
+        }
+
+        print theme('page', $output, t("Trackback URL"));
+    } elseif (is_numeric(arg(1)) && $node = node_load(array("nid" => arg(1)))) {
+        header("Content-Type: text/xml");
+        print trackback_receive($node);
+    } else {
+        drupal_goto();
+    }
 }
 
 function trackback_nodeapi(&$node, $op, $arg = 0) {
+  $node = trackback_load_node($node);
   switch ($op) {
     case "form post":
-      return form_textfield(t("Trackback URL"), "tb_url", $node->tb_url, 40, 255, t("Enter a URL to send the trackback to."));
+      $node->tb_url = $node->toping;
+      return form_textarea(t("Trackback URL"), "tb_url", $node->tb_url, 70, 3, t("Enter URLs to send the trackback to."));
     case "insert":
     case "update":
-      if ($node->tb_url && $node->nid) {
+      # send trackback only for published post
+      if ($node->nid && $node->status == 1
+        && ($node->tb_url || variable_get("trackback_autodiscovery",1)))
         trackback_send($node);
-      }
   }
 }
 
+function trackback_insert($node) {
+  db_query("INSERT INTO tb (pinged, toping, nid) VALUES ('%s', '%s', %d)",
+    $node->pinged, $node->toping, $node->nid);
+}
+
+function trackback_update($node) {
+  db_query("UPDATE {tb} SET pinged = '%s', toping = '%s' WHERE nid = %d",
+    $node->pinged, $node->toping, $node->nid);
+}
+
+function trackback_delete(&$node) {
+  db_query("DELETE FROM {tb} WHERE nid = %d", $node->nid);
+}
+
+function trackback_load($node) {
+  return db_fetch_object(db_query("SELECT pinged, toping FROM {tb} WHERE nid = %d", $node->nid));
+}
+
+function trackback_load_node($node) {
+  if ($result = trackback_load($node)) {
+    foreach ($result as $key => $value)
+      $node->$key = $value;
+  }
+  return $node;
+}
+
 function trackback_link($type, $node = 0, $main = 0) {
   if ($type == 'system') {
     menu('trackback', t('trackback'), trackback_page, 0, MENU_HIDE);
   }
   elseif ($type == "node") {
-    $link = l(t("trackback url"), "trackback/$node->nid");
+    $link = l(t("trackback url"), "trackback/url/$node->nid");
     if (!$main) {
-      $url = url("node/view/$node->nid");
-      $tb_url = url("trackback/$node->nid");
+      $url = url("node/view/$node->nid", NULL, NULL, 1);
+      $tb_url =  url("trackback/$node->nid", NULL, NULL, 1);
       $link .= "\n<!--\n";
       $link .= "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">\n";
       $link .= "<rdf:Description rdf:about=\"$url\" dc:identifier=\"$url\" dc:title=\"$node->title\" trackback:ping=\"$tb_url\" />\n";
@@ -221,4 +337,17 @@
   }
   return $result;
 }
-?>
+
+function trackback_blogadmin($type = "") {
+  $list = array();
+
+  if ($type == "options") {
+    if (user_access("administer site configuration")) {
+      $list[l(t("Trackback options"),"admin/system/modules/trackback")] = t("Configure trackback options");
+    }
+  }
+
+  return $list;
+}
+
+?>
diff -urN drupal-4.4.1/modules/upload.module drupal4blog/modules/upload.module
--- drupal-4.4.1/modules/upload.module	Thu Jan  1 07:30:00 1970
+++ drupal4blog/modules/upload.module	Tue May 18 02:06:37 2004
@@ -0,0 +1,322 @@
+<?php
+// $Id$
+
+function upload_help($section) {
+  $output = "";
+
+  switch ($section) {
+    case 'admin/system/modules#description':
+      $output = t("Enables quick and easy file upload to drupal.");
+      break;
+    case 'admin/upload/help':
+    case 'admin/system/modules/upload':
+      $output = t("Allows quick and easy file upload to drupal. You can define permissions to upload and download file in the %userperm configuration. The permission 'download files' only works if 'Download Method' is set to Private in %sysconf. You also need to make sure your File System path is not accessible from the web.",
+        array("%userperm" => l(t("user permission"),"admin/user/permission"),
+              "%sysconf"  => l(t("system configuration"), "admin/system")));
+      break;
+  }
+  return $output;
+}
+
+function upload_perm() {
+  return array("upload files (simple)", 
+               "maintain files (simple)", 
+               "download files (simple)");
+}
+
+function upload_settings() {
+  if (!file_check_directory(file_create_path(variable_get('upload_path', 'public')))) 
+    $error['upload_path'] = theme('error', t('Directory does not exists, or is not writable.'));
+
+  $output = "";
+
+  $output .= form_textfield(t("Upload path"), "upload_path", variable_get("upload_path", "public"), 30, 255, t("Subdirectory in the directory '%dir' where upload files will be stored.", array('%dir' => variable_get("file_directory_path", "files") . FILE_SEPARATOR)) . $error['upload_path']);
+
+  $output .= form_textfield(t("Maximum file size"), "upload_filesize", variable_get("upload_filesize", 1024), 10, 10, t("Maximum file size for file upload, in kB. Default 1024kb or 1Mb."));
+
+  return $output;
+}
+
+function upload_link($type, $node = 0, $main) {
+  if ($type  == 'system') {
+    if (user_access('upload files (simple)'))
+      menu('upload', t('quick upload'), 'upload_page', 0, MENU_HIDE);
+    if (user_access('maintain files (simple)'))
+      menu('admin/upload', t('manage files'), 'upload_admin', 0);
+  }
+}
+
+function upload_page() {
+  $op = $_POST['op'] ? $_POST['op'] : arg(1);
+
+  if (!user_access("upload files (simple)"))
+    drupal_goto();
+
+  switch ($op) {
+    case 'Replace':
+      print theme('popup', _upload_upload(1), '');
+      break;
+    case 'Upload':
+      print theme('popup', _upload_upload(0), '');
+      break;
+    default:
+      print theme('popup', _upload_form(), '');
+  }
+}
+
+function _upload_form() {
+  drupal_set_title(t('Quick upload file'));
+  $output .= "<div class=\"standard\">";
+  $output .= form_file(t("Upload file"), "upload_file", 30, 
+              "You need to specify a file to upload.");
+  $output .= form_submit(t('Upload'));
+  $output .= form_submit(t('Replace'));
+  $output .= "<p>".t("'Upload' will not replace existing file. Use 'Replace' if you wish to override existing file.")."</p>";
+  $output .= "</div>";
+
+  # construct the form
+  $param["method"] = "post";
+  $param["options"]["enctype"] = "multipart/form-data";
+  return form($output, ($param['method'] ? $param['method'] : 'post'), $param['action'], $param['options']);
+}
+
+function _upload_upload($replace = 0) {
+  $edit = $_POST['edit'];
+  $upload_file = file_check_upload('upload_file');
+
+  if ((!$upload_file) || !file_exists($upload_file->path)) {
+    drupal_set_message(theme("error",t("You need to specify a file to upload.")));
+    return _upload_form();
+  }
+
+  if (filesize($upload_file->path)/1024 > variable_get("upload_filesize",1024)) {
+    drupal_set_message(theme('error',t('Maximum upload size is ').variable_get("upload_filesize", 1024)."kb.".filesize($upload_file->path)));
+    return _upload_form();
+  }
+
+  $dest = variable_get("upload_path","public").FILE_SEPARATOR.$upload_file->name;
+
+  if (!$replace && file_exists(file_create_path($dest))) {
+    drupal_set_message("File already existed!");
+    return _upload_form();
+  } 
+
+  file_save_upload('upload_file',$dest,1);
+
+  $url = file_create_url($dest);
+  if (preg_match("/\.(gif|jpg|png)$/i",$upload_file->name)) {
+    $size = getimagesize(file_create_path($dest));
+    $html = "<img src=\"$url\" alt=\"$upload_file->name\" border=\"0\"";
+    if ($size[0] && $size[1])
+     $html .= " width=\"$size[0]\" height=\"$size[1]\"";
+    $html .= "/>";
+  } else {
+    $html = "<a href=\"$url\">Download file</a>";
+  }
+
+  $output = "";
+  $output .= form_textarea(t("HTML code"),"html",$html,35,3, t("This is the HTML code which you can paste into your entry."));
+  $output .= form_button(t('Close'), "op", "button",
+    array("onClick" => "window.close()"));
+
+  watchdog("special", "upload file ".$upload_file->name, l("view file",$url));
+
+  return form($output);
+}
+
+function upload_admin() {
+  $op = $_POST["op"];
+  $edit = $_POST["edit"];
+
+  if (!user_access("maintain files (simple)"))
+    drupal_goto();
+
+  if (arg(2)) {
+    $output = _upload_admin_file(escapeshellcmd(arg(2)));
+  } else {
+    $output = _upload_admin_overview();
+  }
+
+  print theme("page",$output);
+}
+
+function _upload_filerow($dir,$file) {
+  $ffile = $dir.FILE_SEPARATOR.$file;
+  $info = stat($ffile);
+  if ($info['size'] > 1024*1024) 
+    $size = (int) ($info['size']/(1024*1024))."Mb";
+  else if ($info['size'] > 1024)
+    $size = (int) ($info['size']/1024)."kb";
+  else
+    $size = $info['size']."b";
+  return array(
+    array("data" => l($file,"admin/upload/$file") ),
+    array("data" => $size ),
+    array("data" => format_date($info['mtime']) ),
+  );
+}
+
+function _upload_admin_overview() {
+  $dir = file_create_path(variable_get('upload_path', 'public'));
+  if (!file_check_directory($dir)) {
+    drupal_set_message(t("The upload directory isn't configured properly."));
+    return drupal_goto("admin/system/modules/upload");
+  }
+
+  $output = "";
+  if ($dh = opendir($dir)) {
+    $headers = array( 
+      array("data" => t("filename") ),
+      array("data" => t("size")  ),
+      array("data" => t("date") ),
+    );
+
+    while ($file = readdir($dh)) {
+      if (is_dir($dir.FILE_SEPARATOR.$file)) continue;
+      $rows[] = _upload_filerow($dir,$file);
+    }
+    closedir($dh);
+
+    $url = url("upload");
+    $rows[] = array(array("data" => "<a href=\"javascript:void(window.open('$url','popup','width=350,height=250,resizable=yes'))\">Upload files</a>", "colspan" => 3));
+
+    $output .= theme("table",$headers, $rows);
+  }
+  return $output;
+}
+
+function _upload_admin_file($file) {
+  $op = $_POST['op'];
+  $edit = $_POST['edit'];
+
+  $dir = file_create_path(variable_get('upload_path', 'public'));
+  if (!file_exists($dir.FILE_SEPARATOR.$file)) {
+    drupal_set_message(t("No such file!"));
+    return drupal_goto("admin/upload");
+  }
+
+  switch ($op) {
+    case t('Delete'):
+      $ffile = $dir.FILE_SEPARATOR.$file;
+      @unlink($ffile);
+      watchdog("special", "delete file ".$file, "deleted");
+      drupal_goto("admin/upload");
+      break;
+
+    case t('Rename'):
+      $edit['rename'] = escapeshellcmd($edit['rename']);
+      $edit['rename'] = preg_replace("/[^A-Za-z0-9\-\_]/",".",$edit['rename']);
+      $edit['rename'] = preg_replace("/^[\.\/]+/","",$edit['rename']);
+
+      $ffile = $dir.FILE_SEPARATOR.$file;
+      $dest  = $dir.FILE_SEPARATOR.$edit['rename'];
+
+      if (file_exists($dest)) {
+        drupal_set_message(t("There is already another file by that name."));
+        return drupal_goto("admin/upload/$file");
+      }
+
+      if (copy($ffile,$dest)) {
+        @unlink($ffile);
+        $url = file_create_url(variable_get("upload_path","public").FILE_SEPARATOR.$edit['rename']);
+        watchdog("special", "rename file '$file' to '".$edit['rename']."'", l("view file",$url));
+        return drupal_goto("admin/upload/".$edit['rename']);
+      } else {
+        watchdog("error", "unable to rename file '$file' to '".$edit['rename']."'");
+        drupal_set_message(t("Error renaming file!"));
+        return drupal_goto("admin/upload/$file");
+      }
+      break;
+
+    default:
+      $headers = array( 
+        array("data" => t("filename") ),
+        array("data" => t("size")  ),
+        array("data" => t("date") ),
+      );
+    
+      $rows[] = _upload_filerow($dir,$file);
+      $output = theme("table", $headers, $rows);
+    
+      $form .= form_textfield(t("Rename"), "rename", $file, 30, 128);
+      $form .= form_submit(t("Rename"));
+      $form .= form_submit(t("Delete"));
+      $output .= form($form);
+      break;
+  }
+
+  return $output;
+}
+
+function upload_file_download($file) {
+  if (user_access("download files (simple)")) {
+    $file = file_create_path($file);
+    return array('Content-type: '.mime_content_type($file));
+  }
+}
+
+/*
+** goes into theme.inc?
+**/
+function theme_popup($content, $title = NULL, $breadcrumb = NULL) {
+  if (isset($title)) {
+    drupal_set_title($title);
+  }
+  if (isset($breadcrumb)) {
+    drupal_set_breadcrumb($breadcrumb);
+  }
+
+  $output = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
+  $output .= "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
+  $output .= "<head>";
+  $output .= " <title>". (drupal_get_title() ? drupal_get_title() : variable_get('site_name', "drupal")) ."</title>";
+  $output .= drupal_get_html_head();
+
+  $output .= " </head>";
+  $output .= " <body style=\"background-color: #fff; color: #000;\"". theme("onload_attribute"). "\">";
+  $output .= "<table border=\"0\" cellspacing=\"4\" cellpadding=\"4\"><tr>";
+  $output .= "<td style=\"vertical-align: top;\">";
+
+  $output .= "<h1>" . drupal_get_title() . "</h1>";
+  if ($help = menu_get_active_help()) {
+    $output .= "<small>$help</small><hr />";
+  }
+
+  $output .= "\n<!-- begin content -->\n";
+  $output .= $content;
+  $output .= "\n<!-- end content -->\n";
+
+  $output .= "</td></tr></table>";
+  $output .= theme_closure();
+  $output .= "</body></html>";
+
+  return $output;
+}
+
+function upload_blogadmin($type) {
+  $list = array();
+  
+  if ($type == "block") {
+    if (user_access('upload files (simple)')) {
+      $url = url("upload");
+      $list[] = "<a href=\"javascript:void(window.open('$url','popup','width=350,height=250,resizable=yes'))\">quick upload</a>";
+    }
+
+    if (user_access('maintain files (simple)'))
+      $list[] = l(t("file manager"), "admin/upload");
+  } else if ($type == "options") {
+      $list[l(t("Upload options"),"admin/system/modules/upload")] = t("Configure upload options.");
+  }
+
+  return $list;
+}
+
+if (!function_exists ("mime_content_type")) {
+  function mime_content_type ($file) {
+    $mime = exec ("file -bi " . escapeshellcmd($file));
+    if ($mime) return $mime;
+    return "application/octet-stream";
+  }
+}
+
+?>
