代码相关 | 咸水鳄

咸水鳄



WP升级到2.7版本(或更高)以后 设置 > 常规 选项页内容不全的问题

Category: 代码相关

前一阵升级了这个WP到2.7版本, 今儿想把博客名字改下, nuts改成guts. 结果发现WP后台的 设置 > 常规 选项卡里根本没有 保存更改 这个按钮, 进一步回忆发现原来的时间日期格式什么的都没了. 如图,  时区根本没有选项, 下面就是一片空白.

image

一开始以为是浏览器CSS的兼容问题, FF里把CSS关了, 看裸页, 发现还是一样, PHP在服务器端生成页面的时候好像就没生成全, 根据以前多次二逼经历的经验, 可能是memory_limit的问题. php.ini里的肯定够大了, 于是去WP根目录里找wp-settings.php , 前面的注释结束, 第13行

define(‘WP_MEMORY_LIMIT’, ’32M’);

顺手改成64M试试.

define(‘WP_MEMORY_LIMIT’, ’64M’);

保存, 上传.

好使了. 如图, 下面那些该有现在全都出来了.

image

具体是咋回事还不太明白, 总之现在好使了就行.



如果你忘记了DotnetNuke站点的host和admin密码…

Category: 代码相关

今儿在办公室发生一很无语的事, 有关我的一个DNN(dotnetnuke)项目的. 这个项目是几个月前开始做的, 一个Project Issue Registration System, 后台数据库都已经做完了, 只剩下网站前台, 由于这是个公司的内部项目, 后来的几个网站都是政府还有其它公司的, 优先级比较高, 所以一直在做后来的项目而把这个就一直撂置了, 这几天刚刚把后来的项目都sign off了, 开始有闲, 准备把这个PIRS捡起来做完.

结果把项目打开一运行就傻了, 这是个基于DNN框架的网站, 我把host和admin密码全忘了, 因为当初也是还在开发阶段, 所以根本没设别的用户, 试遍了我自己常用的密码组合, 还有公司的密码组合, 全不行.. 直接无语.  由于host密码不能用密码找回找到, 所以只能走数据库这一步了.

上SQL server, 进去了直奔dbo.aspnet_Membership, 密码是带salt和DNN自己另设的密文加密的, 我头脑一热加手一抖直接把admin和host的密码和salt删了, 然后想用其它站数据库里的密码和salt复制过来, 结果没用, 然后又用hash generator 做了数个加密后的密文+ salt 复制过去, 依然无效. 然后突然想起来,  DNN的加密机制不太一样, 每个DNN站的web.config里自己有个独特的密文, 不同站的不一样, 这一下直接不能上了. 这回事情比原来还严重了, 不仅密码忘了, 原来的密码也没了, salt也没了. -.-|||

OK, 事已至此, 咱上google上找一下先吧, 别自己再乱搞了. 搜索一下, 还真找出不少方案来. 后来才知道, 这些方案在我目前的情况下都不适用, 不过那是后话, 我先把这些解决办法列出来, 方便一下看这篇文章的人.

 

方案一

这个理论上适用于所有情况(但是实际上是痴人说梦..)

  1. 在你DNN网站上注册一个新用户. 如果你的注册按钮被你在站点设置里关掉了, 那就去SQL server上把dbo.Portals表里的UserRegistration值改成2.
  2. 用你开的registration建个新用户(把密码记住.. -.-|||)
  3. 再进数据库, 找到dbo.ASPNet_Membership表
  4. 到你新建的那个用户那一行中把password, passwordsalt的密文都复制到你的host用户那一行的同样列中(host是superuser).
  5. 重新用你的host和你新设用户的密码登录DNN然后再把你新建的那个用户删掉就可以了.

很不幸的是, 我的DNN网站的出于当初开发时的安全考虑被我关闭了, 而且他所说的改UserRegistration值的方法是无效的, 改过后Register依然没有在login module中出现.

 

方案二

这个是需要你已经知道一个帐号的用户名和密码, 然后用下面的SQL query实现对host的密码的替换.

1
2
3
4
5
SELECT password, passwordformat, passwordsalt
FROM aspnet_membership am 
INNER JOIN aspnet_users auON (au.userid = am.userid) 
INNER JOIN aspnet_applications aaON (au.applicationId = aa.applicationid)WHERE au.username = 'admin' 
AND aa.applicationname = 'DotNetNuke'

 

然后把你得到的password, passwordformat, passwordsalt复制到一个地方, 下面的query中从’TestUser’那行开始, 分别对应 用户名, password, passwordsalt, ChangeTime, passwordFormat. 所以你用你刚复制下来的替换下面这几个就可以了.

 

1
2
3
4
5
6
7
8
9
DECLARE @changeDate datetime
SET @changeDate = getdate()
--set the password
exec aspnet_Membership_setPassword 'DotNetNuke', 
'TestUser', 
'DM1tZvBjM+27Eck5eI1TWFeG42XuJnMuin3jqFOtMjS83RN6d7dFbQ==', 
'4e5Bb5jOOMYu/JFXVdRmlA==',
@changeDate, 
2

 

那么很不幸的, 这个方案也是无效的因为我根本没有任何一个知道密码的帐号.而且据我所知DNN 4.4.1以后的版本也不再使用Application ID了, 而是使用Application Name. 所以这里也需要做些小修改才能生效.

 

方案三

在SQL server 运行这个query

1
2
3
4
5
6
7
8
9
10
11
12
Declare @UserName NVarChar(255)
Declare @NewPassword NVarChar(255)
Declare @PasswordSalt NVarChar(128)
Declare @Application NVarChar(255)
-- 在下面的单引号间输入你要做的修改(用户名, 密码)
-- 别留任何空格除非你特意要留..
SET @UserName = 'admin' -- 这个是DNN默认的admin用户, 这里我们要改成host
 
SET @NewPassword = 'newpassword' -- 这里是你的新密码
SET @Application = (SELECT [ApplicationID] FROM aspnet_Users WHERE UserName=@UserName)
SET @PasswordSalt = (SELECT PasswordSalt FROM aspnet_Membership WHERE UserID IN (SELECT UserID FROM aspnet_Users WHERE UserName=@UserName))
Exec dbo.aspnet_Membership_ResetPassword @Application, @UserName, @NewPassword, 10, 10, @PasswordSalt, -5

根据这个query来看, 这也是一个DNN 4.4.1以前的方案,但是我做了小量修改, 依然不能在新版本的DNN上有任何效果. 因为他是基于你没有删SALT的基础上的, 而很不幸, 我把密码+SALT都删没了.  失败.

 

方案四

这个是一个老外的query, 无数老外跟着comment了说好用, 但是很不幸, 他的原理是跟方案一相同的, 也需要你有一个已知密码的帐号, 只不过用query的形式完成了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
DECLARE @databaseName VARCHAR(128)
SELECT @databaseName = DB_NAME()
 
PRINT 'RESET PASSWORD IN DATABASE : ' + @databaseName
PRINT '-----------------------------' + REPLICATE('-', DATALENGTH(@databaseName ));
 
DECLARE @knownUserName NVARCHAR(128)
DECLARE @lostUserName NVARCHAR(128)
DECLARE @lostUserId NVARCHAR(128)
DECLARE @knownPassword NVARCHAR(128)
DECLARE @knownSalt NVARCHAR(128)
 
SET @knownUserName = 'Tonic'
SET @lostUserName = 'host'
 
SELECT @knownPassword = Password, @knownSalt = PasswordSalt
FROM aspnet_Membership
INNER JOIN aspnet_users
ON aspnet_Membership.UserId = aspnet_users.UserId
WHERE UserName = @knownUserName;
 
PRINT ''
PRINT 'Known Password for "' + @knownUserName + '" is : ' + @knownPassword
PRINT 'Known Password Salt for "' + @knownUserName + '" is : ' + @knownSalt
 
SELECT @lostUserId = aspnet_Membership.UserId
FROM aspnet_Membership
INNER JOIN aspnet_users
ON aspnet_Membership.UserId = aspnet_users.UserId
WHERE UserName = @lostUserName;
 
PRINT ''
PRINT 'UserID for "' + @lostUserName + '" is : ' + @lostUserId
PRINT ''
 
IF (DATALENGTH(@lostUserName) <= 0 OR @lostUserName IS NULL)
PRINT 'Invalid Lost User Name ' + @lostUserName
ELSE BEGIN
IF (DATALENGTH(@knownUserName) <= 0 OR @knownUserName IS NULL)
PRINT 'Invalid Lost User Name ' + @lostUserName
ELSE BEGIN
IF (DATALENGTH(@knownPassword) <= 0 OR @knownPassword IS NULL)
PRINT 'Invalid Known Password ' + @knownPassword
ELSE BEGIN
IF (DATALENGTH(@knownSalt) <= 0 OR @knownSalt IS NULL)
PRINT 'Invalid Known Salt ' + @knownSalt
ELSE BEGIN
PRINT ''
PRINT 'BEFORE'
SELECT LEFT(UserName, 12) AS UserName, aspnet_Membership.UserId, LEFT(Email, 20) AS Email, Password, PasswordSalt
FROM aspnet_Membership INNER JOIN aspnet_users ON aspnet_Membership.UserId = aspnet_users.UserId
WHERE UserName IN ( @knownUserName, @lostUserName );
PRINT ''
PRINT 'Changing Password for User Id : "' + @lostUserId + '" to "' + @knownPassword + '"'
PRINT ''
UPDATE aspnet_Membership
SET Password = @knownPassword,
PasswordSalt = @knownSalt
-- SELECT UserId, Password, PasswordSalt
-- FROM aspnet_Membership
WHERE UserId = @lostUserId;
PRINT ''
PRINT 'AFTER'
SELECT LEFT(UserName, 12) AS UserName, aspnet_Membership.UserId, LEFT(Email, 20) AS Email, Password, PasswordSalt
FROM aspnet_Membership INNER JOIN aspnet_users ON aspnet_Membership.UserId = aspnet_users.UserId
WHERE UserName IN ( @knownUserName, @lostUserName );
END
END
END
END
GO
PRINT '' PRINT ' * * * END OF SCRIPT * * *' PRINT '' GO

显然, 前面已经提过, 我没有一个现成的知道密码的帐号, 所以再次失败.

方案五

由于我之前的失败都因为没有一个可以工作的而且知道密码的帐号, 而又不能在网站上注册新帐号, 于是我找到了一个方法可以用SQL创建一个新帐号.

query如下

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
SELECT m.password, m.passwordsalt, m.passwordformat
FROM aspnet_users u
    INNER JOIN aspnet_membership m
        ON (u.userid = m.userid)
WHERE u.UserName = 'TestUser'
SELECT PortalId,
     PortalName
FROM Portals
DECLARE @ApplicationName nvarchar(256)
SET @ApplicationName = 'DotNetNuke'
DECLARE @UserName nvarchar(256) 
SET @UserName = 'NewUser' --The new user
DECLARE @Password nvarchar(128)
--From the existing user
SET @Password = 'LLSXX8xW6+0EbrV4JBzL/YenA1D6BBfRnkYY7FtQvNGmmPOhVdPiAA=='
DECLARE @PasswordSalt nvarchar(128)
--From the existing user
SET @PasswordSalt = 'P40ky5tExsx37nUIFnCWZQ=='
DECLARE @Email nvarchar(256)
SET @Email = 'TestingAccount@test.com' --You can set this to whatever you want
DECLARE @PasswordQuestion nvarchar(256)
SET @PasswordQuestion = ''
DECLARE @PasswordAnswer nvarchar(128)
SET @PasswordAnswer = ''
DECLARE @IsApproved bit
SET @IsApproved = 1
DECLARE @CurrentTimeUtc datetime 
SET @CurrentTimeUtc = GETDATE()
DECLARE @CreateDate datetime
SET @CreateDate = @CurrentTimeUtc
DECLARE @UniqueEmail int
SET @UniqueEmail = 0
DECLARE @PasswordFormat int
SET @PasswordFormat = 2 --NOTE: Value from existing user!
DECLARE @PortalId int
SET @PortalId = 0    --The id of your portal
Declare @UserId uniqueidentifier
DECLARE @DNNUserId int
 
--Make the stored procedure call
EXEC dbo.aspnet_Membership_CreateUser @ApplicationName, @Username, @Password,
                @PasswordSalt, @email, @passwordquestion, @PasswordAnswer, 
                @IsApproved, @CurrentTimeUtc, @CreateDate, @UniqueEmail,
                @PasswordFormat, @UserId
 
--Insert the record into the DotNetNuke users table
INSERT INTO users (Username, FirstName, LastName, IsSuperUser, Email,
                    DisplayName, UpdatePassword)
    VALUES(@Username, 'My', 'NewAccount', 0, @Email, 'New Account', 0)
 
--Get the new userid, from the DNN users table
SELECT @dnnuserid = userid
FROM Users
WHERE username = @Username
 
--Now, insert the record into the user portals table
INSERT INTO UserPortals (userId, PortalId, CreatedDate)
    VALUES(@dnnuserid, @PortalId, GETDATE()) 
 
--Now Give the user permissions to the RECISTERED Users group
INSERT INTO UserRoles (userId, roleId)
SELECT @dnnuserid,
        roleId
FROM Roles
WHERE RoleName = 'Registered Users'

然而我不得不再次不幸的告诉大家, 从这个query来看, 要使用这个query建立一个DNN新用户, 也是需要事先有一个知道密码, salt, applicationname的帐户才可以的, 可悲的是我的密码和salt密文已经被我完全删干净了. 再次失败.

 

成功方案

 

经过了这数次失败以后, 我终于放弃google了, 看来这次真的无法找到我要的答案, 既然数据库方向我无法找到结果, 那么只能从代码上动手脚了, 不就是想注册新用户么, 我开始找login module的code.

image 

DNN的这个目录下存放着login module的代码, 打开后开始查找对portal setting里Userregistration属性的判定, 经过一翻查找和测试, 总算找到了, Page_Load里面的这一段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
            If Not Request.IsAuthenticated Then
                If Page.IsPostBack = False Then
                    Try
                        If Not Request.QueryString("username") Is Nothing Then
                            txtUsername.Text = Request.QueryString("username")
                        End If
                        If Not Request.QueryString("verificationcode") Is Nothing Then
                            If PortalSettings.UserRegistration = PortalRegistrationType.VerifiedRegistration Then
                                ' Comment this line above and the "End If" below out if you can't login as admin or host 
                                '   and can't change the register setting in SQL and don't even have an password-known account 
                                '   and really really desperatly want to register a new user.   -- Kang 10.07.2008
 
                                'Display Verification Rows 
                                rowVerification1.Visible = True
                                rowVerification2.Visible = True
                                txtVerification.Text = Request.QueryString("verificationcode")
                            End If
                        End If
 
                    Catch
                        'control not there 
                    End Try
                End If

这段代码中的comment是我加的.. (当时实在很无语), 判定网站是否开放注册的部分就是其中If PortalSettings.UserRegistration = PortalRegistrationType.VerifiedRegistration Then 和下面的End IF这两行, 我把他们前面加个’ 给comment掉再重新编译运行网站,  register就出来了, 之后我把自己新注册的用户在数据库中的superuser设成true(dbo.Users表里面), 然后用这个帐号登录DNN, 把host和admin的salt随便写一个在数据库里加上, 再把他俩的密码reset, 然后重新change password为我想要的, 大功告成. 本来也可以用上面几个方案中给出的换密码的办法, 不过看了这么久的query我实在不想再弄了, 直接去万恶的DNN后台里改了.

希望对跟我一样犯了愚蠢错误的DNN开发人员有所帮助.

真的很长啊, 谢谢观赏.



如何在Netbeans中开发Android程序.

Category: 代码相关

Google Android项目的用IDE开发时通常是Eclipse + Android SDK + Android plugin for Eclipse.  Eclipse因为有IBM撑腰, 前几年一直是Java IDE的首选..不过现在Sun公司经过多年的摸黑和偷窥(..-_-|||)  从NetBeans 5.5开始  就已经让很多的JAVA开发者开始接受Sun自己的Java IDE, 目前又新推出了NetBeans 6.0.1, 无论从哪方面讲, 都已经是可以和Eclipse相提并论甚至很多方面也已经强过了Eclipse (尤其是俺学校做作业开始要求用NetBeans了….)  所以俺一直在找寻在NetBeans下开发Android的方法… 写作业用NetBeans , 做Android用Eclipse 那我不是吃饱了没事闲的给自己找罪受么… 于是, 答案被俺在NetBeans的wiki上找到.. 下面就分享下..

*****插播刚看的新闻(April 3rd, 2008): 美国最大的通信公司AT&T 已经同意将推出运行Google Android操作系统的手机*****

 

首先需要下载以下的程序

NetBeans

Android SDK

Android plugins for NetBeans (Undroid)

 

1. 安装Undroid(为Netbeans设计的Android 开发插件)

下载插件并安装, Tools-> Plugins -> Downloaded

确定你安装了Platform Support 和Project Support模块. 再装个Examples看看例子也不错..

image

2. 填加 Android Platform

装完插件后, 你需要从Tools-> Java Platforms中填加Android Platform

image

指向你的Android SDK目录

image

3. 创建新的Android项目

从Files-> New Projects.  你可以看到分类里有一个新项目叫Android

image

换不换默认程序名随你便…

 image

新Android项目的结构应该是下面这样的

image

MainActivity.java的代码如下

package org.me.androidapplication1;

import android.app.Activity;
import android.os.Bundle;

/**
 *
 * @author amit
 */
public class MainActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        // ToDo add your GUI initialization code here
    }

}
4. 运行项目
现在就可以试着运行一下了, 运行成功的话, Android模拟器就会跳出来
image
 5. NetBeans中Android 的Hello World
填加一行
TextView tv = new TextView(this);
tv.setText("Hello, Android");
setContentView(tv);
在这一行的上面
// ToDo add your GUI initialization code here
 

然后你会发现Netbeans告诉你"Cannot find symbol". 这是因为还需要导入TextView…(-_-|||..)

Netbeans里导个这东西很简单.

image
 代码现在应该看起来是这样的
package org.me.androidapplication1;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

/**
 *
 * @author amit
 */
public class MainActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

       TextView tv = new TextView(this);
       tv.setText("Hello, Android");
       setContentView(tv);
    }

}
再次运行, 俺们的Hello World 就出来了.
image 
 附:  Android SDK M5-rc15 发布后 Netbeans的Android开发插件Undroid无法运行的解决方案:
http://abhrajit.blogspot.com/2008/03/undroid-and-android-sdk-m5-rc15.html


Lutz Roeder’s .Net Reflector 5.1

Category: 代码相关
标签:, ,

非常好用的.net 反编译程序. 目前最新版本是5.1

拿来反编译dnn module 里的dll文件还是挺有用的…

截个图.

HouseMenu的

reflector.jpg

作者自己写的介绍:
Reflector for .NET

Reflector is the class browser, explorer, analyzer and documentation viewer for .NET. Reflector allows to easily view, navigate, search, decompile and analyze .NET assemblies in C#, Visual Basic and IL.

网址: http://www.aisto.com/roeder/dotnet/

我上传了一个最新版本提供下载, since 作者的网站经常上不去… ===> reflector.zip