Develop and Download Open Source Software

Browse CVS Repository

Contents of /xoonips/AL/commonal.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.83 - (show annotations) (download) (as text)
Fri Mar 11 20:00:28 2005 UTC (19 years, 1 month ago) by orrisroot
Branch: MAIN
Changes since 1.82: +5 -1 lines
File MIME type: text/x-c++src
- Autotoolized XooNiPs Abstract Layer projects.
- changelog.cc commonal.cc index.cc item.cc :
    included <time.h> header file for undefined data type 'time_t' error.

1 /*
2 *
3 * $Revision: 1.82 $
4 * $Log: commonal.cc,v $
5 * Revision 1.82 2005/03/11 07:11:30 tani
6 * itemid_t配列の長さ(*iidsLen)の初期化処理を追加.
7 *
8 * Revision 1.81 2005/03/11 00:34:57 tani
9 * アイテムのアクセス権チェックにcertify_state追加.
10 *
11 * Revision 1.80 2005/03/09 07:27:37 aga4096
12 * ・activate=0ならloginUserに失敗するよう修正.
13 *
14 * Revision 1.79 2005/03/07 01:20:09 aga4096
15 * ・getItemCountGroupByIndexで未承認アイテム・インデックスを数えないよう修正.
16 *
17 * Revision 1.78 2005/03/05 02:28:05 aga4096
18 * ・個人領域のインデックスが Private と表示されるよう修正.
19 *
20 * Revision 1.77 2005/03/05 01:48:35 aga4096
21 * ・getItemCountGroupByIndexを作成.
22 *
23 * Revision 1.76 2005/03/04 06:13:28 aga4096
24 * ・updateIndexで、同じ名前の兄弟があるか名前が空であるならエラーにした.
25 *
26 * Revision 1.75 2005/03/03 10:13:00 aga4096
27 * ・isValidSessionでtimestampを更新するよう修正.
28 * ・sessionはisValidSessionしない限り1時間でタイムアウトするよう修正.
29 * ・loginUser, createSessionでタイムアウトしたsessionを削除するよう修正.
30 *
31 * Revision 1.74 2005/02/26 05:11:31 tani
32 * getGroupItemID追加.
33 *
34 * Revision 1.73 2005/02/25 07:41:35 tani
35 * getGroupItemID追加.
36 * item, indexのlimitフィールドを登録,更新処理に追加.
37 *
38 * Revision 1.72 2005/02/25 01:03:42 tani
39 * dbtype==DBTYPE_SQLITEの時の処理を分岐.
40 *
41 * Revision 1.71 2005/02/24 11:32:55 aga4096
42 * ・updateGroupでグループインデックスの名前を変更するよう修正.
43 *
44 * Revision 1.70 2005/02/23 06:39:28 tani
45 * isGuestEnabled: 設定を読み込むテーブルを変更.
46 *
47 * Revision 1.69 2005/02/22 02:39:30 tani
48 * public_item_target_user_all関数を追加.
49 * SQL中のpublic_item_target_user_allの比較式をpublic_item_target_user_all関数に置換.
50 * sessionテーブルのLEFT JOINの条件にsidのチェックを追加.
51 * DB問合せ処理の高速化.
52 *
53 * Revision 1.68 2005/02/21 05:46:18 tani
54 * getItemCountを追加.
55 * dumpItemID, getItemsの問合せを高速化.
56 *
57 * Revision 1.67 2005/02/19 02:06:11 tani
58 * 承認状態の権限チェックに作成者を追加.
59 *
60 * Revision 1.66 2005/02/16 10:03:13 youi
61 * publication_year/month/mdayに対応.
62 *
63 * Revision 1.65 2005/02/16 07:37:17 youi
64 * insertItem, updateItem, getItems: publication_dateに対応.
65 *
66 * Revision 1.64 2005/02/15 02:35:47 youi
67 * SQLINTEGERからSQLLENへ型変更.
68 *
69 * Revision 1.63 2005/02/10 02:33:16 aga
70 * ・zipCreateをコメントアウトしていたのを戻した.
71 *
72 * Revision 1.62 2005/02/09 11:11:52 youi
73 * deleteItemにアイテムに関係するエントリの削除処理を追加.
74 *
75 * Revision 1.61 2005/02/09 07:23:50 aga
76 * ・URL to My Personal Archive をDB・ALから消した.
77 *
78 * Revision 1.60 2005/02/09 02:14:15 aga
79 * ・initializeDB()にdbtype引数を追加(SQLite用).
80 *
81 * Revision 1.59 2005/02/08 07:15:02 youi
82 * pubmedパース処理:
83 *
84 * Revision 1.58 2005/02/08 06:40:51 youi
85 * pubmedComplete:ジャーナルの完全なタイトルを取得してpubmed_tにセット.
86 *
87 * Revision 1.57 2005/02/03 12:04:58 youi
88 * getOwnPublicItemIDを定義.
89 * binder_item_linkのテーブル名を修正.
90 *
91 * Revision 1.56 2005/01/29 09:49:22 youi
92 * syslog_printf: デバッグメッセージ出力関数を定義した.
93 * getCertifyPermission: チェック用のsqlを定義した.
94 * SQLINTEGER->SQLLENへ型を変更した.
95 * getItemPermission: モデレータであるか?の判断条件を修正.
96 *
97 * Revision 1.55 2005/01/28 07:01:38 youi
98 * getItemIDByIndexID: 対象となるアイテムの条件見直し.
99 * SQLAllocHandle失敗時のメッセージを追加.
100 *
101 * Revision 1.54 2005/01/28 00:36:58 aga
102 * ・freeStringで落ちることがあるのを修正.
103 *
104 * Revision 1.53 2005/01/27 08:30:35 youi
105 * getIndexIDByItemIDを定義した.
106 *
107 * Revision 1.52 2005/01/25 06:46:50 aga
108 * ・Bindersを含むindexはdeleteIndex不可.
109 * ・getItemsがエラーを出すことがあるのを修正.
110 *
111 * Revision 1.51 2005/01/24 10:50:29 youi
112 * freeItemType,getItemTypes関数を追加した.
113 *
114 * Revision 1.50 2005/01/24 01:54:38 youi
115 * 引数の型修飾を変更.
116 * dumpItemID, getItemIDByBinderID, getItemIDByIndexID
117 * 関数追加
118 * getPrivateItemID, getUncertifiedLink
119 *
120 * Revision 1.49 2005/01/22 09:30:58 youi
121 * setLastErrorStringの宣言を追加した.
122 *
123 * Revision 1.48 2005/01/22 04:18:22 aga
124 * ・loginUser, insertAccount内ではmd5()を行わないよう修正.
125 *
126 * Revision 1.47 2005/01/22 02:41:14 aga
127 * ・amazon補完を作成.
128 *
129 * Revision 1.46 2005/01/21 01:36:11 youi
130 * pubmed補完機能を追加した.
131 *
132 * Revision 1.45 2005/01/19 10:07:53 aga
133 * ・ゲストユーザ向けの修正.
134 *
135 * Revision 1.44 2005/01/19 06:01:59 youi
136 * 関数追加
137 * getConfigValue
138 * setConfigValue
139 * getChangeLogs
140 * insertChangeLog
141 * getItemIDByBinderID
142 * registerBinderItem
143 * unregisterBinderItem
144 * getIndexPermission
145 * freeString
146 * freeChangeLog
147 * 引数にcriteria_tを追加
148 * getItemIDByIndexID
149 * 引数の順序を変更
150 * getCertifyState
151 * setCertifyState
152 * getCertifyPermission
153 * sessionID2UID,querySimple,queryGetUnsignedIntの利用
154 * insertItemの内部でPrivateIndexへ登録を行なう
155 * getItems: getItemPermissionを使った読み込み権限チェック.
156 *
157 * Revision 1.43 2005/01/19 01:42:15 aga
158 * ・x_xnpaccount_indexのgid,uidが0にならないよう修正.
159 *
160 * Revision 1.42 2005/01/19 00:51:29 aga
161 * ・insertIndexでx_xnpaccount_index.index_idがおかしいのを修正.
162 *
163 * Revision 1.41 2005/01/19 00:06:51 aga
164 * ・updateIndexで、同じ名前の兄弟があるか名前が空であるならエラーにした.
165 * ・createSessionで、uidがPlatformユーザでないかactivateされていないならエラーにした.
166 *
167 * Revision 1.40 2005/01/17 00:15:05 aga
168 * ・deleteIndex, updateIndexに失敗することがあるのを修正.
169 *
170 * Revision 1.39 2005/01/15 05:38:10 youi
171 * insertAccount: 文字列バッファのサイズ調整など.
172 * updateAccount: 文字列バッファのサイズ調整など.
173 * アイテム管理関数を定義した.
174 * insertItem, getItem, getItems, dumpItemID, updateItem, deleteItemなど.
175 * freeGID, freeUID: 引数の型を修正.
176 *
177 * Revision 1.38 2005/01/15 00:39:16 aga
178 * ・x_xnpaccount_item_basicの構造を変更.
179 *
180 * Revision 1.37 2005/01/14 10:36:59 aga
181 * ・index関係の処理を追加.
182 * ・insertAccountでprivate indexを作成するよう修正.
183 * ・insertGroupでgroup index を作成するよう修正.
184 *
185 * Revision 1.36 2005/01/13 04:19:22 aga
186 * ・VPをXNPに変換.
187 *
188 * Revision 1.35 2005/01/06 07:20:17 youi
189 * WIN32定義時のインクルードの追加.
190 * MySQL APIに関するヘッダファイルを削除.
191 * deleteAccount: 所属するPlatformグループからの削除を内蔵した.
192 * insertAccount: ユーザ登録と同時にデフォルトPlatformグループへ登録する.
193 * deleteMember: デフォルトPlatformグループからの削除を禁止する.
194 * deleteMemberNoLimitの定義.
195 *
196 * Revision 1.34 2004/12/28 04:38:14 aga
197 * ・logoutUser()の修正.
198 *
199 * Revision 1.33 2004/12/27 05:56:23 youi
200 * odbcDiagString: STMT以外のハンドルも処理するように変更した.
201 * syslogメッセージの処理を追加した.
202 *
203 * Revision 1.32 2004/12/25 09:46:47 youi
204 * MySQL+MyODBCで動作するように修正した.
205 *
206 * Revision 1.31 2004/12/21 11:42:59 youi
207 * コメントの引数,戻り値の説明などを追加.
208 *
209 * Revision 1.30 2004/12/18 10:24:54 youi
210 * IMPORT_MYSQLDLLを定義したとき,MYSQLのDLLを動的リンクするプロトタイプ宣言が
211 * 有効になるように修正した.
212 *
213 * Revision 1.29 2004/12/18 01:12:29 youi
214 * freeResultの関数名をfree<データ型>に変更した.
215 *
216 * Revision 1.28 2004/12/14 12:02:08 youi
217 * __WIN__を定義したときはwindowsのdll作成に必要な処理を行なう.
218 * USE_SYSLOGを定義したときはsyslogdへメッセージを出力する.
219 * getAccounts: uidsLenが0のときの処理を追加した.
220 *
221 * Revision 1.27 2004/12/06 11:34:47 aga
222 * ・uninitializeDB()を追加.
223 *
224 * Revision 1.26 2004/12/06 10:17:36 youi
225 * mysql_use_resultの取得結果を残さず取り出すため,
226 * while( row = mysql_fetch_row(result) );を挿入.
227 *
228 * Revision 1.25 2004/12/06 07:24:33 youi
229 * insertAccount, insertGroup:
230 * 新規追加した情報に対応するユーザID,グループIDを第三引数に書き込む.
231 *
232 * Revision 1.24 2004/12/06 01:45:50 aga
233 * ・コメントつけ.
234 * ・開放忘れ修正.
235 *
236 * Revision 1.23 2004/12/04 09:21:10 aga
237 * ・xnp_config → xnpaccount_config.
238 *
239 * Revision 1.22 2004/12/03 07:17:21 youi
240 * isModeratorでアクセスするデータベーステーブル名を修正.
241 *
242 * Revision 1.21 2004/12/01 10:28:58 youi
243 * DBカラム名の変更に伴う修正
244 * institute -> division
245 * organizaion -> company_name
246 *
247 * Revis1.20 2004/12/01 04:37:04 youi
248 * freeResult: unsigned int* を int* へ修正.
249 * コメント部に関数の説明を追記.
250 *
251 * Revision 1.19 2004/11/30 06:40:11 youi
252 * 関数を追加(gidExists, uidExists)
253 * getGroupCountを定義.
254 * getGroupsByUidを定義.
255 * isGroupAdminを修正.
256 * dumpGroupAdminsを定義.
257 * deleteMemberを定義.
258 * insertMemberを定義.
259 * getMembersを定義.
260 * isModeratorを定義.
261 *
262 * Revision 1.18 2004/11/30 05:46:32 aga
263 * ・sessionからremoteHostを削除.
264 *
265 * Revision 1.17 2004/11/27 09:35:49 youi
266 * isActivatedを定義.
267 * activateを定義.
268 * dumpUidを定義.
269 *
270 * Revision 1.16 2004/11/27 06:29:29 youi
271 * getAccountCountを定義.
272 * dumpGidsを定義.
273 * insertGroup, deleteGroup, updateGroupを定義.
274 * getGroup, getGroupsを定義.
275 * データベース初期前の呼出に対し,RES_DB_NOT_INITIALIZEDを返す処理を各関数に追加
276 * (未対応の関数が残っている)
277 *
278 * Revision 1.15 2004/11/27 02:22:22 aga
279 * ・initializeDB前にaddSlashes()を呼ぶと落ちるのを修正.
280 *
281 * Revision 1.14 2004/11/27 01:07:31 youi
282 * criteria2str: LIMITとORDER BYの順番を入れ替えた.
283 *
284 * Revision 1.13 2004/11/27 00:35:39 youi
285 * getAccountsを定義.
286 * getAccountを修正,内部でgetAccountsを呼び出す.
287 * criteria2strを定義.
288 *
289 * Revision 1.12 2004/11/26 09:45:28 youi
290 * getAccountを定義.
291 *
292 * Revision 1.11 2004/11/26 08:16:26 aga
293 * ・getSession, loginUser, createSession, freeResult(const session_t*) 修正.
294 *
295 * Revision 1.10 2004/11/26 07:57:42 youi
296 * updateAccount, deleteAccountを定義.
297 * mysql_query失敗時はstderrへエラーコードとエラーメッセージを出力.
298 *
299 * Revision 1.9 2004/11/26 07:38:02 aga
300 * ・FAILUE -> FAILURE.
301 *
302 * Revision 1.8 2004/11/26 06:36:55 aga
303 * ・createSession, getSession を作成.
304 *
305 * Revision 1.7 2004/11/26 04:51:47 youi
306 * dbprefixを定義した.
307 * insertAccountを定義した.
308 * isValidSessionIDを定義した.
309 *
310 * Revision 1.6 2004/11/26 04:35:55 aga
311 * ・loginUser(), logoutUser()を作成.
312 *
313 * Revision 1.5 2004/11/26 01:08:25 aga
314 * ・addSlashes()作成.
315 *
316 * Revision 1.4 2004/11/25 12:14:29 youi
317 * getUidの処理を定義した.
318 *
319 * Revision 1.3 2004/11/25 11:13:59 youi
320 * getLastErrorString/setLastErrorStringを定義.
321 *
322 * Revision 1.2 2004/11/25 08:55:19 youi
323 * 引数の型を修正.
324 * freeResultを追加.
325 *
326 * Revision 1.1 2004/11/25 05:14:58 youi
327 * initial version
328 *
329 *
330 */
331 #ifdef WIN32
332 #include <windows.h>
333 #endif
334
335 #ifdef USE_SYSLOG
336 #include <syslog.h>
337 #endif
338
339 #include <stdio.h>
340 #include <stdlib.h>
341 #include <string.h>
342 #include <string>
343 #include <assert.h>
344 #include <time.h>
345 #include <sql.h>
346 #include <sqlext.h>
347 #include <libxml/xmlreader.h>
348
349 using namespace std;
350
351 #include "common.h"
352 #include "account.h"
353 #include "group.h"
354 #include "session.h"
355 #include "item.h"
356 #include "itemtype.h"
357 #include "criteria.h"
358 #include "commonal.h"
359 #include "item.h"
360 #include "index.h"
361 #include "changelog.h"
362 #include "pubmed.h"
363 #include "amazonbook.h"
364
365 static string dbprefix; //!< XOOPSデータベーステーブルのPREFIX
366 static dbtype_t dbtype; //!< MySQL/SQLite
367
368 static SQLHANDLE henv = NULL;
369 static SQLHANDLE hdbc = NULL;
370 static SQLHANDLE hstmt = NULL;
371
372 static bool processEsummary(xmlTextReaderPtr reader, pubmed_t* p);
373 static bool processEsearch(xmlTextReaderPtr reader, pubmed_t* p, int* DocID );
374 static void processEfetch(xmlTextReaderPtr reader, pubmed_t* p);
375 static int streamPubmedFile(const char *filename, pubmed_t* p);
376 static result_t insertIndexInternal( sessionid_t sid, index_t *index, indexid_t *xid );
377 static string odbcDiagString( SQLSMALLINT HandleType, SQLHANDLE hstmt, SQLRETURN sqlcode );
378 static result_t deleteMemberNoLimit( sessionid_t sid, groupid_t gid, userid_t uid );
379 static result_t getXoopsModuleConfigValue( const char *module, const char *key, char **value );
380 static void setLastErrorString( const char* str );
381 static result_t checkTitleConflict( sessionid_t sid, indexid_t parentIndexID, const char *title, bool *conflict );
382
383 void syslog_printf( char* format, ... )
384 {
385 #ifdef USE_SYSLOG
386 va_list ap;
387 va_start(ap, format);
388 openlog( "commonal", LOG_ODELAY, LOG_USER );
389 vsyslog( LOG_DEBUG, format, ap );
390 #endif
391 }
392
393 /**
394 *
395 * public_item_target_userの設定値が'all'ならtrueをかえす
396 * 設定値の取得に失敗した場合,'all'以外の場合はfalseをかえす
397 *
398 */
399 static bool public_item_target_user_all( )
400 {
401 char* value = 0;
402 bool public_item_target_user_all = false;
403 if( getConfigValue( XNP_CONFIG_PUBLIC_ITEM_TARGET_USER_KEY, &value ) == RES_OK ){
404 public_item_target_user_all = ( strcmp( value, XNP_CONFIG_PUBLIC_ITEM_TARGET_USER_ALL ) == 0 );
405 freeString( value );
406 }
407 return public_item_target_user_all;
408 }
409
410 static result_t countResultRows( const char* sql, SQLLEN* count )
411 {
412 result_t ret = RES_ERROR;
413 SQLRETURN sqlcode;
414 SQLHANDLE hstmt = NULL;
415 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
416 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql, strlen( sql ) ) ) == SQL_SUCCESS ){
417 *count = 0;
418 while( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ) ( *count )++;
419 ret = RES_OK;
420 }else{
421 string s( "SQLExecDirect in countResultRows " );
422 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
423 s += "sql=";
424 s += string( sql );
425 setLastErrorString( s.c_str( ) );
426 ret = RES_DB_QUERY_ERROR;
427 }
428 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
429 }
430 return ret;
431 }
432
433
434 /**
435 *
436 * インデックス登録,アイテム更新を行なったときの承認状態の初期値を,
437 * システム設定にしたがって返します.
438 *
439 */
440 static certify_t getInitialCertifyStateFromConfig( )
441 {
442 char* certify_item_val;
443 certify_t ret = index::NOT_CERTIFIED;
444
445 if( getConfigValue( XNP_CONFIG_CERTIFY_ITEM_KEY, &certify_item_val ) == RES_OK ){
446 if( strcmp( certify_item_val, XNP_CONFIG_CERTIFY_ITEM_AUTO ) == 0 ){
447 //certify automatic
448 ret = index::CERTIFIED;
449 }else if( strcmp( certify_item_val, XNP_CONFIG_CERTIFY_ITEM_ON ) == 0 ){
450 //certify by moderator or group admin
451 ret = index::CERTIFY_REQUIRED;
452 }
453 syslog_printf( "\ngetInitialCertifyStateFromConfig certify_item_val=%s", certify_item_val );
454 freeString( certify_item_val );
455 }
456 return ret;
457 }
458
459 /**
460 *
461 * セッションに対応付けられたユーザが,PlatformユーザとしてActivateさ
462 * れているかを返す
463 *
464 * @param sid セッションID
465 * @return true Activateされている
466 * @return false Activateされている,またはエラー
467 *
468 */
469 static bool isActivatedBySession( sessionid_t sid )
470 {
471 const session_t* session;
472 if( getSession( sid, &session ) == RES_OK ){
473 userid_t sess_uid = session -> getUID( );
474 freeSession( session );
475 return isActivated( sid, sess_uid );
476 }
477 return false;
478 }
479
480 /**
481 *
482 * セッションに対応付けられたユーザが,モデレータであるか?
483 *
484 *
485 * @param sid セッションID
486 * @return true モデレータ
487 * @return false モデレータでない,またはエラー
488 *
489 */
490 static bool isModeratorBySession( sessionid_t sid )
491 {
492 const session_t* session;
493 if( getSession( sid, &session ) == RES_OK ){
494 userid_t sess_uid = session -> getUID( );
495 freeSession( session );
496 return isModerator( sid, sess_uid );
497 }
498 return false;
499 }
500
501
502
503
504 /** SQLを実行する。結果は捨てる。
505 * @param sql sql
506 * @return result_t
507 */
508 static result_t querySimple( const char *functionName, string &sql ){
509 result_t ret = RES_ERROR;
510 SQLRETURN sqlcode;
511 SQLHANDLE hstmt = NULL;
512 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
513 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), strlen( sql.c_str() ) ) ) == SQL_SUCCESS ){
514 ret = RES_OK;
515 }else{
516 string s( "SQLExecDirect in querySimple " );
517 s += functionName;
518 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
519 s += "sql=";
520 s += sql;
521 setLastErrorString( s.c_str( ) );
522 ret = RES_DB_QUERY_ERROR;
523 }
524 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
525 }
526 else {
527 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in querySimple " );
528 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
529 setLastErrorString( s.c_str( ) );
530 ret = RES_ERROR;
531 }
532 return ret;
533 }
534
535 /** SQLを実行し、1行目の最初の整数値(NULLなら0とみなす)のみ受け取る。
536 * @param sql sql
537 * @param u 整数値を受け取る変数。
538 * @return result_t
539 */
540 static result_t queryGetUnsignedInt( const char *functionName, string &sql, unsigned int *u ){
541 result_t ret = RES_ERROR;
542 SQLRETURN sqlcode;
543 SQLHANDLE hstmt = NULL;
544
545 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
546 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), strlen( sql.c_str() ) ) ) == SQL_SUCCESS ){
547 SQLUINTEGER sInt = 0;
548 SQLLEN len = 0;
549 SQLBindCol( hstmt, 1, SQL_C_ULONG, &sInt, 0, &len );
550 if( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
551 if ( len == SQL_NULL_DATA )
552 sInt = 0;
553 *u = sInt;
554 ret = RES_OK;
555 }else{
556 string s( "SQLFetch in queryGetUnsignedInt " );
557 s += functionName;
558 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
559 setLastErrorString( s.c_str( ) );
560 ret = RES_ERROR;
561 }
562 }else{
563 string s( "SQLExecDirect in queryGetUnsignedInt " );
564 s += functionName;
565 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
566 s += "sql=";
567 s += sql;
568 setLastErrorString( s.c_str( ) );
569 ret = RES_DB_QUERY_ERROR;
570 }
571 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
572 }
573 else {
574 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in queryGetUnsignedInt " );
575 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
576 setLastErrorString( s.c_str( ) );
577 ret = RES_ERROR;
578 }
579 return ret;
580 }
581
582 /**
583 *
584 * 文字列コピー.
585 * 指定文字数をコピーし,バッファの最後をNULL終端する.
586 * ( dstのサイズ >= len + 1 )であること
587 *
588 */
589 static char* strncpy2( char* dst, const char* src, int len )
590 {
591 strncpy( dst, src, len );
592 dst[ len ] = '\0';
593 syslog_printf( "\nstrncpy2 '%s'\n", dst );
594 return dst;
595 }
596
597 /**
598 *
599 * SQLの実行結果からエラー文字列を生成する
600 *
601 * @param hstmt SQL文のハンドル
602 * @param sqlcode SQLExecDirect,SQLExecuteの戻り値
603 * @return エラー文字列
604 */
605 static string odbcDiagString( SQLSMALLINT HandleType, SQLHANDLE hstmt, SQLRETURN sqlcode )
606 {
607 string s;
608 if( sqlcode == SQL_ERROR || sqlcode == SQL_SUCCESS_WITH_INFO ){
609 SQLCHAR SQLState[6];
610 SQLINTEGER NativeError;
611 SQLCHAR MessageText[ 1024 ];
612 SQLSMALLINT TextLength;
613 SQLGetDiagRec( HandleType, hstmt, 1, SQLState, &NativeError, MessageText, 1024, &TextLength );
614
615 s += string( (char*)MessageText );
616 s += " SQLSTATE=";
617 s += string( (char*)SQLState );
618
619 }
620 s += " sqlcode=";
621 s += intToString( sqlcode );
622 return s;
623 }
624
625 /**
626 *
627 * 指定カラムの値を取り出してその文字列を返す
628 *
629 */
630 string getResultCol( SQLHANDLE hstmt, int col )
631 {
632 string s;
633 SQLRETURN sqlcode;
634 SQLCHAR BinaryPtr[5000];
635 SQLLEN BinaryLenOrInd;
636 SQLINTEGER NumBytes;
637
638 syslog_printf( "getResultCol" );
639 while ( ( sqlcode = SQLGetData(hstmt, col, SQL_C_CHAR, BinaryPtr, sizeof(BinaryPtr),
640 &BinaryLenOrInd)) != SQL_NO_DATA) {
641 syslog_printf( "SQLGetData BinaryLenOrInd=%d", BinaryLenOrInd );
642 NumBytes = (BinaryLenOrInd > 5000) || (BinaryLenOrInd == SQL_NO_TOTAL) ? 5000 : BinaryLenOrInd;
643 if( NumBytes <= 0 ) break;
644 else if( NumBytes > 0 ){
645 s += string( (char*)BinaryPtr, NumBytes );
646 }
647 }
648 syslog_printf( "getResultCol returns %s", s.c_str() );
649 return s;
650 }
651
652
653 /**
654 *
655 * クォートなどを\記号でエスケープする
656 *
657 * @param str addslashesすべき文字列。NULL指定不可。
658 * @return 変換後の文字列
659 */
660 string addSlashes( const char *str )
661 {
662 if ( hdbc == NULL ){
663 string s;
664 return s;
665 }else{
666 string s( str );
667 return s;
668 }
669
670 int len = strlen(str) * 3;
671 char* dst = new char[ len ];
672 const char* from = str;
673 char* to = dst;
674 while( *from != '\0' ){
675 switch( *from ){
676 case '\'':
677 case '\"':
678 case ';':
679 *to = '\\'; to++;
680 break;
681 }
682 *to = *from; to++;
683 from++;
684 }
685 *to = '\0';
686 string s( dst );
687 delete[] dst;
688 return s;
689 }
690
691 /** Xoops Module の設定を調べる
692 * @param module モジュールのdirname
693 * @param key 設定のkey
694 * @param value 設定を返す変数。
695 * @return
696 */
697 static result_t getXoopsModuleConfigValue( const char *module, const char *key, char **value ){
698 SQLRETURN sqlcode;
699 SQLHANDLE hstmt = NULL;
700 result_t result = RES_ERROR;
701
702 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
703 string sql = "SELECT conf_value "
704 " from " + dbprefix + "_config as tc, " + dbprefix + "_modules as tm "
705 " where tm.mid=tc.conf_modid and tm.dirname = ? and tc.conf_name = ? ";
706 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
707 SQLLEN cbModule = SQL_NTS, cbKey = SQL_NTS;
708 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, strlen(module), 0, (SQLCHAR *)module, 0, &cbModule );
709 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, strlen(key), 0, (SQLCHAR *)key, 0, &cbKey );
710 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), strlen( sql.c_str() ) ) ) == SQL_SUCCESS ){
711 if ( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
712 string s = getResultCol( hstmt, 1 );
713 *value = new char[s.length()+1];
714 strcpy( *value, s.c_str() );
715 result = RES_OK;
716 }
717 else if ( sqlcode == SQL_NO_DATA ){
718 *value = 0;
719 result = RES_OK;
720 }
721 else {
722 string s( "SQLFetch in getXoopsModuleConfig " );
723 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
724 s += "sql=";
725 s += sql;
726 setLastErrorString( s.c_str( ) );
727 result = RES_ERROR;
728 }
729 }else{
730 string s( "SQLExecDirect in getXoopsModuleConfig " );
731 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
732 s += "sql=";
733 s += sql;
734 setLastErrorString( s.c_str( ) );
735 result = RES_DB_QUERY_ERROR;
736 }
737 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
738 }
739 else {
740 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in getXoopsModuleConfig " );
741 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
742 setLastErrorString( s.c_str( ) );
743 result = RES_ERROR;
744 }
745 return result;
746 }
747
748 /** ゲストユーザがXooNiPsのPublicなアイテムを見ることができるかどうかを返す。
749 */
750 static bool isGuestEnabled(){
751 char *value = 0;
752 result_t result = getConfigValue( XNP_CONFIG_PUBLIC_ITEM_TARGET_USER_KEY, &value );
753 if ( result != RES_OK )
754 return false;
755 if ( value == 0 )
756 return false;
757 bool enabled = ( strcmp( value, XNP_CONFIG_PUBLIC_ITEM_TARGET_USER_ALL ) == 0 );
758 freeString( value );
759 return enabled;
760 }
761
762 /** sidからuidを得る。
763 * @param sid session id
764 * @param uid uidを受け取る変数
765 * @return RES_OK
766 * sidは有効なsessionidである。この場合*uidには有効なuidが入る。
767 * あるいは、公開アイテムを非XooNiPsユーザに公開 かつsidがsession::SID_GUEST(=0)である。この場合、*uidにはaccount::UID_GUEST(=0)が入る。
768 * @return その他 エラー
769 */
770 static result_t sessionID2UID( sessionid_t sid, userid_t *uid ){
771 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
772
773 if ( sid == session::SID_GUEST ){
774 if ( isGuestEnabled() ){
775 *uid = account::UID_GUEST;
776 return RES_OK;
777 }
778 return RES_NO_SUCH_SESSION;
779 }
780 else {
781 string sql = "SELECT uid FROM " + dbprefix + "_xnpaccount_session WHERE sid=" + unsignedIntToString(sid);
782 syslog_printf( "sql=%s", sql.c_str() );
783 return queryGetUnsignedInt( "sessionID2UID", sql, uid );
784 }
785 }
786
787
788
789 /**
790 *
791 * gidの存在をチェック.
792 * DBのアクセス失敗などもfalseとなる.
793 *
794 * @param gid チェックしたいGID
795 * @return true 存在する
796 * @return false 存在しない
797 *
798 */
799 static bool gidExists( groupid_t gid )
800 {
801 string sql;
802 SQLRETURN sqlcode;
803 SQLHANDLE hstmt = NULL;
804
805 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) != SQL_SUCCESS ) {
806 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in gidExists" );
807 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
808 setLastErrorString( s.c_str( ) );
809 return false;
810 }
811
812 sql = "SELECT * FROM " + dbprefix + "_xnpaccount_groups ";
813 sql += "WHERE gid=" + string( unsignedIntToString( gid ) );
814 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) != SQL_SUCCESS ){
815 setLastErrorString( "SQLExecDirect in gidExists" );
816 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
817 return false;
818 }
819
820 if( ( sqlcode = SQLFetch( hstmt ) ) != SQL_SUCCESS ){
821 setLastErrorString( "SQLFetch in gidExists" );
822 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
823 return false;
824 }
825
826 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
827 return true;
828 }
829
830
831 /**
832 *
833 * Platformユーザ情報にuidが存在するかをチェック.
834 * DBのアクセス失敗などもfalseとなる.
835 *
836 * @param uid チェックしたいUID
837 * @return true 存在する
838 * @return false 存在しない
839 *
840 */
841 static bool uidExists( userid_t uid )
842 {
843 bool ret = false;
844 string sql;
845 SQLRETURN sqlcode;
846
847 sql = "SELECT * FROM " + dbprefix + "_xnpaccount_users ";
848 sql += "WHERE uid=" + string( unsignedIntToString( uid ) );
849 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
850 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
851 if( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
852 ret = true;
853 }else{
854 string s( "SQLFetch in uidExists ");
855 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
856 s += string( ", sql=" ) + string( sql );
857 setLastErrorString( s.c_str( ) );
858 ret = false;
859 }
860 }else{
861 string s( "SQLExecDirect in uidExists ");
862 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
863 s += string( ", sql=" ) + string( sql );
864 setLastErrorString( s.c_str( ) );
865 ret = false;
866 }
867 }else{
868 string s( "SQLAllocHandle in uidExists ");
869 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
870 setLastErrorString( s.c_str( ) );
871 ret = false;
872 }
873 return ret;
874 }
875
876
877 /**
878 *
879 * criteria を SQLに変換する
880 *
881 *
882 *
883 */
884 string criteria2str( criteria* cri )
885 {
886 string sql;
887
888 const orderby* odrby = cri -> headOrderBy( );
889 if( odrby != 0 ){
890 sql += " ORDER BY " + string( odrby -> getColumn( ) );
891 sql += ( odrby -> getOrder( ) == orderby::DESC ) ? " DESC" : " ";
892 while( ( odrby = cri -> nextOrderBy( ) ) != 0 ){
893 sql += ", " + string( odrby -> getColumn( ) );
894 sql += ( odrby -> getOrder( ) == orderby::DESC ) ? " DESC" : " ";
895 }
896 }
897
898 if( cri -> getLimitStart( ) != 0 || cri -> getLimitRows( ) != 0 ){
899 sql += " LIMIT " + string( intToString( cri -> getLimitStart( ) ) )
900 + ", " + string( intToString( cri -> getLimitRows( ) ) );
901 }
902 return sql;
903 }
904
905
906 /**
907 *
908 * データベースの初期化
909 *
910 * @param dsn DSN
911 * @param user データベースにアクセスするユーザ名
912 * @param password 上記ユーザのパスワード
913 * @param dbname ダミー
914 * @param prefix XOOPSデータベーステーブルのPREFIX
915 * @param dbtype DBTYPE_MYSQL or DBTYPE_SQLITE
916 * @return RES_OK
917 * @return RES_DB_INITIALIZE_ERROR
918 * @return RES_DB_CONNECT_ERROR
919 * @refer result_t
920 */
921 result_t initializeDB( const char* dsn, const char* user, const char* password, const char* dbname, const char* prefix, dbtype_t type )
922 {
923 SQLRETURN sqlcode;
924
925 // 既に接続中なら、一旦切断
926 if ( hdbc != NULL )
927 SQLDisconnect( hdbc );
928
929 dbprefix = prefix;
930 dbtype = type;
931
932 // 初期化と接続
933 // if( SQLAllocEnv( &henv ) != SQL_SUCCESS ) {
934 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv ) ) != SQL_SUCCESS ) {
935 string s( "SQLAllocHandle(SQL_HANDLE_ENV,...) in initializeDB" );
936 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
937 setLastErrorString( s.c_str( ) );
938 syslog_printf( "initializeDB %s", getLastErrorString( ) );
939 return RES_DB_INITIALIZE_ERROR;
940 }
941 //ODBC Ver.3 として振舞うように属性を設定
942 SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
943
944 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc ) ) != SQL_SUCCESS ) {
945 string s( "SQLAllocHandle(SQL_HANDLE_DBC,...) in initializeDB" );
946 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
947 setLastErrorString( s.c_str( ) );
948 syslog_printf( "initializeDB %s", getLastErrorString( ) );
949 return RES_DB_INITIALIZE_ERROR;
950 }
951 //ログインに5秒以上要したらタイムアウトする設定
952 SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);
953
954 if ( ( sqlcode = SQLConnect( hdbc, (SQLCHAR*)dsn, strlen( dsn ), (SQLCHAR*)user, strlen( user ), (SQLCHAR*)password, strlen( password ) ) ) != SQL_SUCCESS ){
955 string s( "SQLConnect in initializeDB " );
956 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
957 setLastErrorString( s.c_str( ) );
958 syslog_printf( "initializeDB %s", getLastErrorString( ) );
959 return RES_DB_CONNECT_ERROR;
960 }
961 syslog_printf( "initializeDB succeed" );
962 return RES_OK;
963 }
964
965 /**
966 *
967 * DB接続があれば、それを開放する。
968 *
969 * @param なし
970 * @return RES_OK
971 */
972 result_t uninitializeDB()
973 {
974 if ( hdbc != NULL ){
975 SQLDisconnect( hdbc );
976 hdbc = NULL;
977 }
978 return RES_OK;
979 }
980
981 /**
982 *
983 * Platformユーザ承認状態取得
984 *
985 * @param sid セッションID
986 * @param uid 状態を取得したいユーザのUID
987 * @return true 承認済み
988 * @return false 未承認
989 *
990 */
991 bool isActivated( sessionid_t sid, userid_t uid )
992 {
993 if( hdbc == NULL ) return false;
994 if( !isValidSessionID( sid ) ) return false;
995
996 bool ret = false;
997 string sql;
998 SQLRETURN sqlcode;
999 SQLHANDLE hstmt = NULL;
1000
1001 sql = "SELECT * FROM " + dbprefix + "_xnpaccount_users ";
1002 sql += "WHERE activate=1 and uid=" + string( unsignedIntToString( uid ) );
1003 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1004 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1005 if( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
1006 ret = true;
1007 }else{
1008 string s( "SQLFetch in isActivated " );
1009 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1010 s += ", sql=" + sql;
1011 setLastErrorString( s.c_str() );
1012 ret = false;
1013 }
1014 }else{
1015 string s( "SQLExecDirect in isActivated " );
1016 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1017 s += ", sql=" + sql;
1018 setLastErrorString( s.c_str() );
1019 ret = false;
1020 }
1021 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1022 }else{
1023 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in isActivated" );
1024 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1025 setLastErrorString( s.c_str( ) );
1026 ret = false;
1027 }
1028 return ret;
1029 }
1030
1031 /**
1032 *
1033 * Platformユーザ承認状態変更
1034 *
1035 * @param sid セッションID
1036 * @param uid 変更したいユーザのUID
1037 * @param activate 承認(true) / 未承認(false)の指定
1038 * @return RES_OK
1039 * @return RES_DB_QUERY_ERROR
1040 * @return RES_NO_SUCH_USER
1041 */
1042 result_t activate( sessionid_t sid, userid_t uid, bool activate )
1043 {
1044 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
1045 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
1046
1047 string sql;
1048 SQLRETURN sqlcode;
1049 result_t ret = RES_ERROR;
1050
1051 sql = "UPDATE " + dbprefix + "_xnpaccount_users ";
1052 sql += "SET activate=" + string( activate ? "1" : "0" );
1053 sql += " WHERE uid=" + string( unsignedIntToString( uid ) );
1054 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1055 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1056 SQLLEN count = 0;
1057 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1058 ret = RES_OK;
1059 }else{
1060 string s( "SQLRowCount in activate ");
1061 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1062 s += string( ", sql=" ) + string( sql );
1063 setLastErrorString( s.c_str( ) );
1064 ret = RES_NO_SUCH_USER;
1065 }
1066 }else{
1067 string s( "SQLExecDirect in activate " );
1068 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1069 s += ", sql=";
1070 s += string( sql );
1071 setLastErrorString( s.c_str( ) );
1072 ret = RES_DB_QUERY_ERROR;
1073 }
1074 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1075 }else{
1076 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in activate" );
1077 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1078 setLastErrorString( s.c_str( ) );
1079 ret = RES_ERROR;
1080 }
1081 return ret;
1082 }
1083
1084 /**
1085 *
1086 * アカウント数を取得する.
1087 *
1088 * @param sid セッションID
1089 * @return アカウント数
1090 *
1091 */
1092 int getAccountCount( sessionid_t sid )
1093 {
1094 if( hdbc == NULL ) return 0;
1095 if( !isValidSessionID( sid ) ) return 0;
1096
1097 int ret = 0;
1098 string sql;
1099 SQLRETURN sqlcode;
1100 SQLHANDLE hstmt = NULL;
1101
1102 //アカウント数を求める
1103 sql = "SELECT COUNT(*) FROM " + dbprefix + "_xnpaccount_users ";
1104 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1105 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1106 SQLUINTEGER count = 0;
1107 SQLLEN len = 0;
1108 SQLBindCol( hstmt, 1, SQL_C_ULONG, &count, 0, &len );
1109 if( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
1110 ret = count;
1111 }else {
1112 string s( "SQLFetch in getAccountCount sql=" );
1113 s += string( sql );
1114 setLastErrorString( s.c_str( ) );
1115 ret = 0;
1116 }
1117 }else{
1118 setLastErrorString( "SQLExecDirect in getAccountCount" );
1119 ret = 0;
1120 }
1121 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1122 }else{
1123 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in getAccountCount" );
1124 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1125 setLastErrorString( s.c_str( ) );
1126 ret = 0;
1127 }
1128 return ret;
1129 }
1130
1131 /**
1132 *
1133 * アカウント削除
1134 * グループからの削除とユーザ情報の削除を行ないます.
1135 *
1136 * @param
1137 * @return RES_OK
1138 * @return RES_ERROR
1139 * @return RES_DB_NOT_INITIALIZED
1140 * @return RES_NO_SUCH_SESSION
1141 * @return RES_DB_QUERY_ERROR
1142 *
1143 */
1144 result_t deleteAccount( sessionid_t sid, userid_t uid )
1145 {
1146 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
1147 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
1148
1149 result_t ret1 = RES_ERROR, ret2 = RES_ERROR;
1150 criteria_t c;
1151 string sql;
1152 groupid_t* gids;
1153 int gidsLen;
1154 SQLRETURN sqlcode;
1155 SQLHANDLE hstmt = NULL;
1156
1157 /*
1158 1. delete user from default platform group
1159 2. delete user profile from xoops_users
1160 3. delete platform user from xnpaccount_users
1161 */
1162
1163 //1. delete user from platform groups
1164 c.clearAll();
1165 if( getGroupsByUid( sid, uid, &c, &gids, &gidsLen ) == RES_OK ){
1166 for( int i = 0; i < gidsLen; i++ )
1167 deleteMemberNoLimit( sid, gids[ i ], uid );
1168 freeGID( gids );
1169 }
1170
1171 //2. delete user profile from xoops_users
1172 sql = "DELETE FROM " + dbprefix + "_users ";
1173 sql += "WHERE uid = " + string( unsignedIntToString( uid ) );
1174 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1175 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1176 SQLLEN count = 0;
1177 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1178 ret1 = RES_OK;
1179 }else{
1180 string s( "SQLRowCount in deleteAccount" );
1181 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1182 s += string( ", sql=" ) + string( sql );
1183 setLastErrorString( s.c_str( ) );
1184 ret1 = RES_NO_SUCH_USER;
1185 }
1186 }else{
1187 string s( "SQLExecDirect in deleteAccount" );
1188 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1189 s += ", sql=";
1190 s += string( sql );
1191 setLastErrorString( s.c_str( ) );
1192 ret1 = RES_DB_QUERY_ERROR;
1193 }
1194 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1195 }else{
1196 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in deleteAccount" );
1197 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1198 setLastErrorString( s.c_str( ) );
1199 ret1 = RES_ERROR;
1200 }
1201
1202 //3. delete platform user from xnpaccount_users
1203 sql = "DELETE FROM " + dbprefix + "_xnpaccount_users ";
1204 sql += "WHERE uid = " + string( unsignedIntToString( uid ) );
1205 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1206 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1207 SQLLEN count = 0;
1208 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1209 ret2 = RES_OK;
1210 }else{
1211 string s( "SQLRowCount in deleteAccount" );
1212 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1213 s += string( ", sql=" ) + string( sql );
1214 setLastErrorString( s.c_str( ) );
1215 ret2 = RES_NO_SUCH_USER;
1216 }
1217 }else{
1218 string s( "SQLExecDirect in deleteAccount" );
1219 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1220 s += ", sql=";
1221 s += string( sql );
1222 setLastErrorString( s.c_str( ) );
1223 ret2 = RES_DB_QUERY_ERROR;
1224 }
1225 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1226 }else{
1227 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in deleteAccount" );
1228 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1229 setLastErrorString( s.c_str( ) );
1230 ret2 = RES_ERROR;
1231 }
1232
1233 //一方でもエラーならエラーを返す
1234 return ret1 != RES_OK ? ret1 : ret2;
1235 }
1236
1237 /**
1238 *
1239 * アカウント情報取得
1240 *
1241 * @param sid セッションID
1242 * @param uid 取得したいユーザのUID
1243 * @param acc 取得したアカウント情報(account_t)のポインタを書き込む引数
1244 * @return RES_OK
1245 * @return RES_DB_NOT_INITIALIZED
1246 * @return RES_NO_SUCH_USER
1247 * @return RES_NO_SUCH_SESSION
1248 * @return RES_DB_QUERY_ERROR
1249 *
1250 */
1251 result_t getAccount( sessionid_t sid, userid_t uid, const account_t** acc )
1252 {
1253 int len;
1254 static criteria c;
1255 result_t res = getAccounts( sid, &uid, 1, &c, acc, &len );
1256 if( len == 0 ) return RES_NO_SUCH_USER;
1257 return res;
1258 }
1259
1260 /**
1261 *
1262 * アカウント情報取得
1263 *
1264 * @param sid セッションID
1265 * @param uids 取得したいユーザのUIDの配列
1266 * @param uidsLen uids配列の要素数
1267 * @param cri 結果の範囲指定,ソート条件指定
1268 * @param accounts 検索結果の配列のポインタを書き込む引数
1269 * @param accountsLen 検索結果の数(配列*accountsの要素数)
1270 * @return RES_OK
1271 * @return RES_DB_NOT_INITIALIZED
1272 * @return RES_NO_SUCH_SESSION
1273 * @return RES_DB_QUERY_ERROR
1274 *
1275 */
1276 result_t getAccounts( sessionid_t sid, const userid_t* uids, int uidsLen, criteria_t* cri, const account_t** accounts, int* accountsLen )
1277 {
1278 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
1279 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
1280 if( uidsLen <= 0 ){
1281 *accounts = new account_t[ 0 ];
1282 *accountsLen = 0;
1283 syslog_printf( "getAccounts succeed len=0" );
1284 return RES_OK;
1285 }
1286
1287 syslog_printf( "begin of getAccounts" );
1288 result_t ret = RES_ERROR;
1289 SQLRETURN sqlcode;
1290 SQLHANDLE hstmt = NULL;
1291 string sql;
1292 account_t* dst = new account_t[ uidsLen ];
1293
1294 sql += "SELECT u1.uid, u1.name, u1.uname, u1.email, u1.url, u1.user_avatar, u1.user_regdate, u1.user_icq, u1.user_from, u1.user_sig, u1.user_viewemail, u1.actkey, u1.user_aim, u1.user_yim, u1.user_msnm, u1.pass, u1.posts, u1.attachsig, u1.rank, u1.level, u1.theme, u1.timezone_offset, u1.last_login, u1.umode, u1.uorder, u1.notify_method, u1.notify_mode, u1.user_occ, u1.bio, u1.user_intrest, u1.user_mailok, u2.activate, u2.address, u2.division, u2.tel, u2.company_name, u2.country, u2.zipcode, u2.fax, u2.notice_mail, u2.notice_mail_since, u2.private_index_id, u2.private_item_number_limit, u2.private_index_number_limit, u2.private_item_storage_limit ";
1295 sql += "FROM " + dbprefix + "_users AS u1, " + dbprefix + "_xnpaccount_users AS u2 ";
1296 sql += "WHERE u1.uid = u2.uid ";
1297 if( uidsLen > 0 ){
1298 syslog_printf( "set uid[%d] value=%d to ...", 0, uids[0] );
1299 sql += "AND ( u1.uid=" + string( unsignedIntToString( uids[ 0 ] ) );
1300 for( int i = 1; i < uidsLen; i++ ){
1301 syslog_printf( "set uid[%d] value=%d to ...", i, uids[i] );
1302 sql += " OR u1.uid=" + string( unsignedIntToString( uids[ i ] ) );
1303 }
1304 sql += " ) ";
1305 }
1306 sql += criteria2str( cri );
1307 syslog_printf( "sql=%s", sql.c_str() );
1308
1309 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1310 syslog_printf( "SQLAllocHandle" );
1311 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1312 syslog_printf( "SQLExecDirect" );
1313 SQLLEN cbUid = 0, cbStorageLimit = 0;
1314 userid_t uid = 0;
1315 SQLDOUBLE storage_limit = 0;
1316 SQLBindCol( hstmt, 1, SQL_C_ULONG, &uid, 0, &cbUid );
1317 SQLBindCol( hstmt, 45, SQL_C_DOUBLE, &storage_limit, 0, &cbStorageLimit );
1318 syslog_printf( "SQLBindCol" );
1319 *accountsLen=0;
1320 for( int i = 0; ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS && i < uidsLen ; i++ ){
1321 syslog_printf( "SQLFetch" );
1322 dst[ i ].setUID( uid );
1323 dst[ i ].setName( getResultCol( hstmt, 2 ).c_str() );
1324 dst[ i ].setUname( getResultCol( hstmt, 3 ).c_str() );
1325 dst[ i ].setEmail( getResultCol( hstmt, 4 ).c_str() );
1326 dst[ i ].setURL( getResultCol( hstmt, 5 ).c_str() );
1327 dst[ i ].setUserAvatar( getResultCol( hstmt, 6 ).c_str() );
1328 dst[ i ].setUserRegdate( atoi( getResultCol( hstmt, 7 ).c_str() ) );
1329 dst[ i ].setUserIcq( getResultCol( hstmt, 8 ).c_str() );
1330 dst[ i ].setUserFrom( getResultCol( hstmt, 9 ).c_str() );
1331 dst[ i ].setUserSig( getResultCol( hstmt, 10 ).c_str() );
1332 dst[ i ].setUserViewemail( atoi( getResultCol( hstmt, 11 ).c_str() ));
1333 dst[ i ].setActkey( getResultCol( hstmt, 12 ).c_str() );
1334 dst[ i ].setUserAim( getResultCol( hstmt, 13 ).c_str() );
1335 dst[ i ].setUserYim( getResultCol( hstmt, 14 ).c_str() );
1336 dst[ i ].setUserMsnm( getResultCol( hstmt, 15 ).c_str() );
1337 dst[ i ].setPass( getResultCol( hstmt, 16 ).c_str() );
1338 dst[ i ].setPosts( atoi( getResultCol( hstmt, 17 ).c_str() ));
1339 dst[ i ].setAttachsig( atoi( getResultCol( hstmt, 18 ).c_str() ));
1340 dst[ i ].setRank( atoi( getResultCol( hstmt, 19 ).c_str() ));
1341 dst[ i ].setLevel( atoi( getResultCol( hstmt, 20 ).c_str() ));
1342 dst[ i ].setTheme( getResultCol( hstmt, 21 ).c_str() );
1343 dst[ i ].setTimezoneOffset( atof( getResultCol( hstmt, 22 ).c_str() ) );
1344 dst[ i ].setLastLogin( atoi( getResultCol( hstmt, 23 ).c_str() ));
1345 dst[ i ].setUmode( getResultCol( hstmt, 24 ).c_str() );
1346 dst[ i ].setUorder( atoi( getResultCol( hstmt, 25 ).c_str() ));
1347 dst[ i ].setNotifyMethod( atoi( getResultCol( hstmt, 26 ).c_str() ));
1348 dst[ i ].setNotifyMode( atoi( getResultCol( hstmt, 27 ).c_str() ));
1349 dst[ i ].setUserOcc( getResultCol( hstmt, 28 ).c_str() );
1350 dst[ i ].setBio( getResultCol( hstmt, 29 ).c_str() );
1351 dst[ i ].setUserIntrest( getResultCol( hstmt, 30 ).c_str() );
1352 dst[ i ].setUserMailok( atoi( getResultCol( hstmt, 31 ).c_str() ));
1353 dst[ i ].setActivate( atoi( getResultCol( hstmt, 32 ).c_str() ));
1354 dst[ i ].setAddress( getResultCol( hstmt, 33 ).c_str() );
1355 dst[ i ].setDivision( getResultCol( hstmt, 34 ).c_str() );
1356 dst[ i ].setTel( getResultCol( hstmt, 35 ).c_str() );
1357 dst[ i ].setCompanyName( getResultCol( hstmt, 36 ).c_str() );
1358 dst[ i ].setCountry( getResultCol( hstmt, 37 ).c_str() );
1359 dst[ i ].setZipcode( getResultCol( hstmt, 38 ).c_str() );
1360 dst[ i ].setFax( getResultCol( hstmt, 39 ).c_str() );
1361 dst[ i ].setNoticeMail( atoi( getResultCol( hstmt, 40 ).c_str() ));
1362 dst[ i ].setNoticeMailSince( atoi( getResultCol( hstmt, 41 ).c_str() ));
1363 dst[ i ].setPrivateIndexID( atoi( getResultCol( hstmt, 42 ).c_str() ));
1364 dst[ i ].setItemNumberLimit( atoi( getResultCol( hstmt, 43 ).c_str() ));
1365 dst[ i ].setIndexNumberLimit( atoi( getResultCol( hstmt, 44 ).c_str() ));
1366 dst[ i ].setItemStorageLimit( storage_limit );
1367 ( *accountsLen )++;
1368 }
1369 *accounts = dst;
1370 syslog_printf( "getAccounts succeed" );
1371 ret = RES_OK;
1372 }else{
1373 string s( "SQLExecDirect in getAccounts" );
1374 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1375 s += string( ", sql=" ) + string( sql );
1376 setLastErrorString( s.c_str( ) );
1377 syslog_printf( "getAccounts %s", getLastErrorString( ) );
1378 ret = RES_DB_QUERY_ERROR;
1379 }
1380 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1381 }else{
1382 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in getAccounts" );
1383 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1384 setLastErrorString( s.c_str( ) );
1385 syslog_printf( "getAccounts %s", getLastErrorString( ) );
1386 ret = RES_DB_QUERY_ERROR;
1387 }
1388 return ret;
1389 }
1390
1391 /**
1392 *
1393 * アカウント登録.
1394 *
1395 * ユーザ情報をデータベースに登録します.
1396 * 登録したユーザ情報に対応するユーザIDをuidに格納します.
1397 *
1398 * @param sid セッション
1399 * @param account 登録するアカウント情報
1400 * @param uid 登録したアカウント情報に対応するユーザID
1401 * @return RES_OK
1402 * @return RES_NO_SUCH_SESSION
1403 * @return RES_DB_QUERY_ERROR
1404 * @return RES_DB_NOT_INITIALIZED
1405 *
1406 */
1407 result_t insertAccount( sessionid_t sid, const account_t* account, userid_t* uid )
1408 {
1409 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
1410 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
1411
1412 string sql;
1413 string tmp;
1414 SQLRETURN sqlcode;
1415 result_t ret = RES_ERROR;
1416
1417 /*
1418 1. insert user profile into xoops_users
1419 2. insert platform user profile into xnpaccount_users
1420 3. add user to default platform group
1421 4. create private index
1422 5. update account set private_index_id=...
1423 */
1424
1425 //1.xoopsのユーザテーブルに書き込む
1426 SQLCHAR uname[ACCOUNT_UNAME_LEN+1], name[ACCOUNT_NAME_LEN+1], email[ACCOUNT_EMAIL_LEN+1], url[ACCOUNT_URL_LEN+1], user_avatar[ACCOUNT_USER_AVATAR_LEN+1], user_icq[ACCOUNT_USER_ICQ_LEN+1], user_from[ACCOUNT_USER_FROM_LEN+1], user_sig[ACCOUNT_USER_SIG_LEN+1], actkey[ACCOUNT_ACTKEY_LEN+1], user_aim[ACCOUNT_USER_AIM_LEN+1], user_yim[ACCOUNT_USER_YIM_LEN+1], user_msnm[ACCOUNT_USER_MSNM_LEN+1], pass[ACCOUNT_PASS_LEN+1], theme[ACCOUNT_THEME_LEN+1], umode[ACCOUNT_UMODE_LEN+1], user_occ[ACCOUNT_USER_OCC_LEN+1], bio[ACCOUNT_BIO_LEN+1], user_intrest[ACCOUNT_USER_INTREST_LEN+1];
1427 SQLINTEGER user_regdate, user_viewemail, posts, attachsig, rank, level, last_login, uorder, notify_method, notify_mode, user_mailok;
1428 SQLDOUBLE timezone_offset;
1429
1430 SQLLEN cbUname = SQL_NTS, cbName = SQL_NTS, cbEmail = SQL_NTS, cbUrl = SQL_NTS, cbUser_avatar = SQL_NTS, cbUser_icq = SQL_NTS, cbUser_from = SQL_NTS, cbUser_sig = SQL_NTS, cbActkey = SQL_NTS, cbUser_aim = SQL_NTS, cbUser_yim = SQL_NTS, cbUser_msnm = SQL_NTS, cbPass = SQL_NTS, cbTheme = SQL_NTS, cbUmode = SQL_NTS, cbUser_occ = SQL_NTS, cbBio = SQL_NTS, cbUser_intrest = SQL_NTS;
1431 SQLLEN cbUser_regdate = 0, cbUser_viewemail = 0, cbPosts = 0, cbAttachsig = 0, cbRank = 0, cbLevel = 0, cbLast_login = 0, cbUorder = 0, cbNotify_method = 0, cbNotify_mode = 0, cbUser_mailok = 0, cbTimezone_offset = 0;
1432
1433 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1434 string sql;
1435 sql = "INSERT INTO " + dbprefix + "_users (uname, name, email, url, user_avatar, user_regdate, user_icq, user_from, user_sig, user_viewemail, actkey, user_aim, user_yim, user_msnm, pass, posts, attachsig, rank, level, theme, timezone_offset, last_login, umode, uorder, notify_method, notify_mode, user_occ, bio, user_intrest, user_mailok) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
1436 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
1437 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
1438 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_UNAME_LEN, 0, uname, 0, &cbUname );
1439 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_NAME_LEN, 0, name, 0, &cbName );
1440 SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_EMAIL_LEN, 0, email, 0, &cbEmail );
1441 SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_URL_LEN, 0, url, 0, &cbUrl );
1442 SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_AVATAR_LEN, 0, user_avatar, 0, &cbUser_avatar );
1443 SQLBindParameter(hstmt, 6, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &user_regdate, 0, &cbUser_regdate );
1444 SQLBindParameter(hstmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_ICQ_LEN, 0, user_icq, 0, &cbUser_icq );
1445 SQLBindParameter(hstmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_FROM_LEN, 0, user_from, 0, &cbUser_from );
1446 SQLBindParameter(hstmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_SIG_LEN, 0, user_sig, 0, &cbUser_sig );
1447 SQLBindParameter(hstmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &user_viewemail, 0, &cbUser_viewemail );
1448 SQLBindParameter(hstmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_ACTKEY_LEN, 0, actkey, 0, &cbActkey );
1449 SQLBindParameter(hstmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_AIM_LEN, 0, user_aim, 0, &cbUser_aim );
1450 SQLBindParameter(hstmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_YIM_LEN, 0, user_yim, 0, &cbUser_yim );
1451 SQLBindParameter(hstmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_MSNM_LEN, 0, user_msnm, 0, &cbUser_msnm );
1452 SQLBindParameter(hstmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_PASS_LEN, 0, pass, 0, &cbPass );
1453 SQLBindParameter(hstmt, 16, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &posts, 0, &cbPosts );
1454 SQLBindParameter(hstmt, 17, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &attachsig, 0, &cbAttachsig );
1455 SQLBindParameter(hstmt, 18, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &rank, 0, &cbRank );
1456 SQLBindParameter(hstmt, 19, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &level, 0, &cbLevel );
1457 SQLBindParameter(hstmt, 20, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_THEME_LEN, 0, theme, 0, &cbTheme );
1458 SQLBindParameter(hstmt, 21, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &timezone_offset, 0, &cbTimezone_offset );
1459 SQLBindParameter(hstmt, 22, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &last_login, 0, &cbLast_login );
1460 SQLBindParameter(hstmt, 23, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_UMODE_LEN, 0, umode, 0, &cbUmode );
1461 SQLBindParameter(hstmt, 24, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &uorder, 0, &cbUorder );
1462 SQLBindParameter(hstmt, 25, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &notify_method, 0, &cbNotify_method );
1463 SQLBindParameter(hstmt, 26, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &notify_mode, 0, &cbNotify_mode );
1464 SQLBindParameter(hstmt, 27, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_OCC_LEN, 0, user_occ, 0, &cbUser_occ );
1465 SQLBindParameter(hstmt, 28, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_BIO_LEN, 0, bio, 0, &cbBio );
1466 SQLBindParameter(hstmt, 29, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_INTREST_LEN, 0, user_intrest, 0, &cbUser_intrest );
1467 SQLBindParameter(hstmt, 30, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &user_mailok, 0, &cbUser_mailok );
1468
1469 strncpy2( (char*)uname, account -> getUname( ), ACCOUNT_UNAME_LEN );
1470 strncpy2( (char*)name, account -> getName( ), ACCOUNT_NAME_LEN );
1471 strncpy2( (char*)email, account -> getEmail( ), ACCOUNT_EMAIL_LEN );
1472 strncpy2( (char*)url, account -> getURL( ), ACCOUNT_URL_LEN );
1473 strncpy2( (char*)user_avatar, account -> getUserAvatar( ), ACCOUNT_USER_AVATAR_LEN );
1474 user_regdate = time( NULL );
1475 strncpy2( (char*)user_icq, account -> getUserIcq( ), ACCOUNT_USER_ICQ_LEN );
1476 strncpy2( (char*)user_from, account -> getUserFrom( ), ACCOUNT_USER_FROM_LEN );
1477 strncpy2( (char*)user_sig, account -> getUserSig( ), ACCOUNT_USER_SIG_LEN );
1478 user_viewemail = account -> getUserViewemail( );
1479 strncpy2( (char*)actkey, account -> getActkey( ), ACCOUNT_ACTKEY_LEN );
1480 strncpy2( (char*)user_aim, account -> getUserAim( ), ACCOUNT_USER_AIM_LEN );
1481 strncpy2( (char*)user_yim, account -> getUserYim( ), ACCOUNT_USER_YIM_LEN );
1482 strncpy2( (char*)user_msnm, account -> getUserMsnm( ), ACCOUNT_USER_MSNM_LEN );
1483 strncpy2( (char*)pass, account -> getPass( ), ACCOUNT_PASS_LEN );
1484 posts = account -> getPosts( );
1485 attachsig = account -> getAttachsig( );
1486 rank = account -> getRank( );
1487 level = account -> getLevel( );
1488 strncpy2( (char*)theme, account -> getTheme( ), ACCOUNT_THEME_LEN );
1489 timezone_offset = account -> getTimezoneOffset( );
1490 last_login = 0;
1491 strncpy2( (char*)umode, account -> getUmode( ), ACCOUNT_UMODE_LEN );
1492 uorder = account -> getUorder( );
1493 notify_method = account -> getNotifyMethod( );
1494 notify_mode = account -> getNotifyMode( );
1495 strncpy2( (char*)user_occ, account -> getUserOcc( ), ACCOUNT_USER_OCC_LEN );
1496 strncpy2( (char*)bio, account -> getBio( ), ACCOUNT_BIO_LEN );
1497 strncpy2( (char*)user_intrest, account -> getUserIntrest( ), ACCOUNT_USER_INTREST_LEN );
1498 user_mailok = account -> getUserMailok( );
1499
1500 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
1501 SQLLEN count = 0;
1502 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1503 //ユーザIDを取得する
1504 if( dbtype == DBTYPE_MYSQL ){
1505 sql = "SELECT LAST_INSERT_ID()";
1506 }else if( dbtype == DBTYPE_SQLITE ){
1507 sql = "SELECT LAST_INSERT_ROWID()";
1508 }
1509 ret = queryGetUnsignedInt( "insertAccount", sql, (unsigned int*)uid );
1510 }else{
1511 string s( "SQLRowCount in insertAccount sql=" );
1512 s += string( sql );
1513 setLastErrorString( s.c_str( ) );
1514 ret = RES_DB_QUERY_ERROR;
1515 }
1516 }else{
1517 string s( "SQLExecute in insertAccount " );
1518 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1519 setLastErrorString( s.c_str( ) );
1520 ret = RES_DB_QUERY_ERROR;
1521 }
1522 }else{
1523 string s( "SQLPrepare in insertAccount " );
1524 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1525 setLastErrorString( s.c_str( ) );
1526 ret = RES_ERROR;
1527 }
1528 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1529 }else{
1530 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in insertAccount" );
1531 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1532 setLastErrorString( s.c_str( ) );
1533 ret = RES_ERROR;
1534 }
1535
1536 if( ret == RES_OK ){
1537 //2.xnpaccountのユーザテーブルに残りの情報を書き込む
1538 SQLUINTEGER activate;
1539 SQLCHAR address[XNP_ACCOUNT_ADDRESS_LEN+1];
1540 SQLCHAR division[XNP_ACCOUNT_DIVISION_LEN+1];
1541 SQLCHAR tel[XNP_ACCOUNT_TEL_LEN+1];
1542 SQLCHAR company_name[XNP_ACCOUNT_COMPANY_NAME_LEN+1];
1543 SQLCHAR country[XNP_ACCOUNT_COUNTRY_LEN+1];
1544 SQLCHAR zipcode[XNP_ACCOUNT_ZIPCODE_LEN+1];
1545 SQLCHAR fax[XNP_ACCOUNT_FAX_LEN+1];
1546 SQLLEN cbAddress = SQL_NTS, cbDivision = SQL_NTS, cbTel = SQL_NTS, cbCompany_name = SQL_NTS, cbCountry = SQL_NTS, cbZipcode = SQL_NTS, cbFax = SQL_NTS;
1547 SQLLEN cbUid = 0, cbActivate = 0, cbNotice_mail = 0, cbNotice_mail_since = 0, cbItem_number_limit = 0, cbIndex_number_limit = 0, cbItem_storage_limit = 0;
1548 SQLUINTEGER notice_mail;
1549 SQLUINTEGER notice_mail_since;
1550 SQLINTEGER item_number_limit;
1551 SQLINTEGER index_number_limit;
1552 SQLDOUBLE item_storage_limit;
1553
1554 if( ret == RES_OK && ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1555 string sql;
1556 sql = "INSERT INTO " + dbprefix + "_xnpaccount_users (uid, activate, address, division, tel, company_name, country, zipcode, fax, notice_mail, notice_mail_since, private_item_number_limit, private_index_number_limit, private_item_storage_limit) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";
1557 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
1558 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
1559 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, uid, 0, &cbUid);
1560 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &activate, 0, &cbActivate);
1561 SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_ADDRESS_LEN, 0, address, 0, &cbAddress);
1562 SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_DIVISION_LEN, 0, division, 0, &cbDivision);
1563 SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_TEL_LEN, 0, tel, 0, &cbTel);
1564 SQLBindParameter(hstmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_COMPANY_NAME_LEN, 0, company_name, 0, &cbCompany_name);
1565 SQLBindParameter(hstmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_COUNTRY_LEN, 0, country, 0, &cbCountry);
1566 SQLBindParameter(hstmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_ZIPCODE_LEN, 0, zipcode, 0, &cbZipcode);
1567 SQLBindParameter(hstmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_FAX_LEN, 0, fax, 0, &cbFax);
1568 SQLBindParameter(hstmt, 10, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &notice_mail, 0, &cbNotice_mail);
1569 SQLBindParameter(hstmt, 11, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &notice_mail_since, 0, &cbNotice_mail_since);
1570 SQLBindParameter(hstmt, 12, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &item_number_limit, 0, &cbItem_number_limit);
1571 SQLBindParameter(hstmt, 13, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &index_number_limit, 0, &cbIndex_number_limit);
1572 SQLBindParameter(hstmt, 14, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &item_storage_limit, 0, &cbItem_storage_limit);
1573
1574 activate = account -> getActivate() ? 1 : 0;
1575 strncpy2( (char*)address, account -> getAddress(), XNP_ACCOUNT_ADDRESS_LEN );
1576 strncpy2( (char*)division, account -> getDivision(), XNP_ACCOUNT_DIVISION_LEN );
1577 strncpy2( (char*)tel, account -> getTel(), XNP_ACCOUNT_TEL_LEN );
1578 strncpy2( (char*)company_name, account -> getCompanyName(), XNP_ACCOUNT_COMPANY_NAME_LEN );
1579 strncpy2( (char*)country, account -> getCountry(), XNP_ACCOUNT_COUNTRY_LEN );
1580 strncpy2( (char*)zipcode, account -> getZipcode(), XNP_ACCOUNT_ZIPCODE_LEN );
1581 strncpy2( (char*)fax, account -> getFax(), XNP_ACCOUNT_FAX_LEN );
1582 notice_mail = account -> getNoticeMail( );
1583 notice_mail_since = time( NULL );
1584 item_number_limit = account -> getItemNumberLimit( );
1585 index_number_limit = account -> getIndexNumberLimit( );
1586 item_storage_limit = account -> getItemStorageLimit( );
1587
1588 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
1589 SQLLEN count = 0;
1590 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1591 ret = RES_OK;
1592 if( ret == RES_OK ){
1593 //3.add new user to default group(not a group admin)
1594 ret = insertMember( sid, group_t::GID_DEFAULT, *uid, false );
1595 }else{
1596 //xoops_usersへinsertしたレコードを削除する
1597 sql = "DELETE FROM " + dbprefix + "_users where uid=";
1598 sql += unsignedIntToString( *uid );
1599 SQLHANDLE hstmt2 = NULL;
1600 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt2 ) ) == SQL_SUCCESS ) {
1601 SQLExecDirect( hstmt2, (SQLCHAR*)sql.c_str(), sql.length() );
1602 SQLFreeHandle( SQL_HANDLE_STMT, hstmt2 );
1603 }
1604 setLastErrorString( "insertMember in insertAccount" );
1605 ret = RES_DB_QUERY_ERROR;
1606 }
1607 }else{
1608 string s( "SQLRowCount in insertAccount sql=" );
1609 s += string( sql );
1610 setLastErrorString( s.c_str( ) );
1611 ret = RES_DB_QUERY_ERROR;
1612 }
1613 }else{
1614 string s( "SQLExecute in insertAccount " );
1615 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1616 setLastErrorString( s.c_str( ) );
1617 ret = RES_DB_QUERY_ERROR;
1618 }
1619 }else{
1620 //xoops_usersへinsertしたレコードを削除する
1621 sql = "DELETE FROM " + dbprefix + "_users where uid=";
1622 sql += unsignedIntToString( *uid );
1623 SQLHANDLE hstmt2 = NULL;
1624 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt2 ) ) == SQL_SUCCESS ) {
1625 SQLExecDirect( hstmt2, (SQLCHAR*)sql.c_str(), sql.length() );
1626 SQLFreeHandle( SQL_HANDLE_STMT, hstmt2 );
1627 }
1628 string s( "SQLExecDirect in insertAccount sql=" );
1629 s += string( sql );
1630 setLastErrorString( s.c_str( ) );
1631 ret = RES_DB_QUERY_ERROR;
1632 }
1633 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1634 }else{
1635 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in insertAccount" );
1636 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1637 setLastErrorString( s.c_str( ) );
1638 ret = RES_ERROR;
1639 }
1640 }
1641
1642 if ( ret == RES_OK ){
1643 //4.private indexを作成
1644
1645 // private index用のsort_number生成
1646 string sql = "select min(sort_number) from " +
1647 dbprefix + "_xnpaccount_index where parent_index_id=" + unsignedIntToString(item::IID_ROOT) +
1648 " and open_level=" + unsignedIntToString(index::OL_PRIVATE);
1649 unsigned int sortNumber;
1650 ret = queryGetUnsignedInt( "insertAccount", sql, &sortNumber );
1651 sortNumber--;
1652 if ( ret == RES_OK ){
1653 // private index作成
1654 index_t index;
1655 index.setItemTypeID(item::ITID_INDEX);
1656 index.setContributorUID(*uid);
1657 index.setParentIndexID(item::IID_ROOT);
1658 index.setOwnerUID(*uid);
1659 index.setOpenLevel(index::OL_PRIVATE);
1660 index.setSortNumber(sortNumber);
1661 index.setTitle(account->getUname());
1662 indexid_t privateXID;
1663 ret = insertIndexInternal( sid, &index, &privateXID );
1664 if ( ret == RES_OK ){
1665 // xnpaccuont_usersのprivate_index_idの書き換え
1666 sql = "UPDATE " + dbprefix + "_xnpaccount_users SET private_index_id="
1667 + unsignedIntToString(privateXID) + " WHERE uid=" + unsignedIntToString(*uid);
1668 ret = querySimple( "insertAccount", sql );
1669 }
1670 }
1671 }
1672
1673 return ret;
1674 }
1675
1676 /**
1677 *
1678 * アカウント情報を変更する.
1679 *
1680 *
1681 * @param sid セッションID
1682 * @param account 変更したいアカウント情報
1683 * @return RES_OK
1684 * @return RES_DB_NOT_INITIALIZED
1685 * @return RES_NO_SUCH_SESSION
1686 * @return RES_DB_QUERY_ERROR
1687 * @return RES_NO_SUCH_USER
1688 * @return RES_ERROR
1689 *
1690 */
1691 result_t updateAccount( sessionid_t sid, const account_t* account )
1692 {
1693 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
1694 if( account == NULL ) return RES_ERROR;
1695 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
1696 if( !uidExists( account -> getUID( ) ) ) return RES_NO_SUCH_USER;
1697
1698 SQLRETURN sqlcode;
1699 result_t ret = RES_ERROR;
1700 SQLHANDLE hstmt = NULL;
1701
1702 //xoopsのユーザテーブルに書き込む
1703 SQLCHAR uname[ACCOUNT_UNAME_LEN+1], name[ACCOUNT_NAME_LEN+1], email[ACCOUNT_EMAIL_LEN+1], url[ACCOUNT_URL_LEN+1], user_avatar[ACCOUNT_USER_AVATAR_LEN+1], user_icq[ACCOUNT_USER_ICQ_LEN+1], user_from[ACCOUNT_USER_FROM_LEN+1], user_sig[ACCOUNT_USER_SIG_LEN+1], actkey[ACCOUNT_ACTKEY_LEN+1], user_aim[ACCOUNT_USER_AIM_LEN+1], user_yim[ACCOUNT_USER_YIM_LEN+1], user_msnm[ACCOUNT_USER_MSNM_LEN+1], pass[ACCOUNT_PASS_LEN+1], theme[ACCOUNT_THEME_LEN+1], umode[ACCOUNT_UMODE_LEN+1], user_occ[ACCOUNT_USER_OCC_LEN+1], bio[ACCOUNT_BIO_LEN+1], user_intrest[ACCOUNT_USER_INTREST_LEN+1];
1704 SQLINTEGER uid, user_regdate, user_viewemail, posts, attachsig, rank, level, last_login, uorder, notify_method, notify_mode, user_mailok;
1705 SQLDOUBLE timezone_offset;
1706
1707 SQLLEN cbUname = SQL_NTS, cbName = SQL_NTS, cbEmail = SQL_NTS, cbUrl = SQL_NTS, cbUser_avatar = SQL_NTS, cbUser_icq = SQL_NTS, cbUser_from = SQL_NTS, cbUser_sig = SQL_NTS, cbActkey = SQL_NTS, cbUser_aim = SQL_NTS, cbUser_yim = SQL_NTS, cbUser_msnm = SQL_NTS, cbPass = SQL_NTS, cbTheme = SQL_NTS, cbUmode = SQL_NTS, cbUser_occ = SQL_NTS, cbBio = SQL_NTS, cbUser_intrest = SQL_NTS;
1708 SQLLEN cbUid = 0, cbUser_regdate = 0, cbUser_viewemail = 0, cbPosts = 0, cbAttachsig = 0, cbRank = 0, cbLevel = 0, cbLast_login = 0, cbUorder = 0, cbNotify_method = 0, cbNotify_mode = 0, cbUser_mailok = 0, cbTimezone_offset = 0;
1709
1710 SQLUINTEGER activate;
1711 SQLCHAR address[XNP_ACCOUNT_ADDRESS_LEN+1];
1712 SQLCHAR division[XNP_ACCOUNT_DIVISION_LEN+1];
1713 SQLCHAR tel[XNP_ACCOUNT_TEL_LEN+1];
1714 SQLCHAR company_name[XNP_ACCOUNT_COMPANY_NAME_LEN+1];
1715 SQLCHAR country[XNP_ACCOUNT_COUNTRY_LEN+1];
1716 SQLCHAR zipcode[XNP_ACCOUNT_ZIPCODE_LEN+1];
1717 SQLCHAR fax[XNP_ACCOUNT_FAX_LEN+1];
1718 SQLLEN cbActivate = 0, cbAddress = SQL_NTS, cbDivision = SQL_NTS, cbTel = SQL_NTS, cbCompany_name = SQL_NTS, cbCountry = SQL_NTS, cbZipcode = SQL_NTS, cbFax = SQL_NTS;
1719 SQLUINTEGER notice_mail, notice_mail_since;
1720 SQLLEN cbNotice_mail = 0, cbNotice_mail_since = 0;
1721
1722 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1723 string sql;
1724
1725 sql = "UPDATE " + dbprefix + "_users SET ";
1726 sql += "uname=?";
1727 sql += ", name=?";
1728 sql += ", email=?";
1729 sql += ", url=?";
1730 sql += ", user_avatar=?";
1731 sql += ", user_regdate=?";
1732 sql += ", user_icq=?";
1733 sql += ", user_from=?";
1734 sql += ", user_sig=?";
1735 sql += ", user_viewemail=?";
1736 sql += ", actkey=?";
1737 sql += ", user_aim=?";
1738 sql += ", user_yim=?";
1739 sql += ", user_msnm=?";
1740 sql += ", pass=?";
1741 sql += ", posts=?";
1742 sql += ", attachsig=?";
1743 sql += ", rank=?";
1744 sql += ", level=?";
1745 sql += ", theme=?";
1746 sql += ", timezone_offset=?";
1747 sql += ", last_login=?";
1748 sql += ", umode=?";
1749 sql += ", uorder=?";
1750 sql += ", notify_method=?";
1751 sql += ", notify_mode=?";
1752 sql += ", user_occ=?";
1753 sql += ", bio=?";
1754 sql += ", user_intrest=?";
1755 sql += ", user_mailok=? ";
1756 sql += " WHERE uid = ?";
1757
1758 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
1759 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
1760 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_UNAME_LEN, 0, uname, 0, &cbUname );
1761 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_NAME_LEN, 0, name, 0, &cbName );
1762 SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_EMAIL_LEN, 0, email, 0, &cbEmail );
1763 SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_URL_LEN, 0, url, 0, &cbUrl );
1764 SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_AVATAR_LEN, 0, user_avatar, 0, &cbUser_avatar );
1765 SQLBindParameter(hstmt, 6, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &user_regdate, 0, &cbUser_regdate );
1766 SQLBindParameter(hstmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_ICQ_LEN, 0, user_icq, 0, &cbUser_icq );
1767 SQLBindParameter(hstmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_FROM_LEN, 0, user_from, 0, &cbUser_from );
1768 SQLBindParameter(hstmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_SIG_LEN, 0, user_sig, 0, &cbUser_sig );
1769 SQLBindParameter(hstmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &user_viewemail, 0, &cbUser_viewemail );
1770 SQLBindParameter(hstmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_ACTKEY_LEN, 0, actkey, 0, &cbActkey );
1771 SQLBindParameter(hstmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_AIM_LEN, 0, user_aim, 0, &cbUser_aim );
1772 SQLBindParameter(hstmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_YIM_LEN, 0, user_yim, 0, &cbUser_yim );
1773 SQLBindParameter(hstmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_MSNM_LEN, 0, user_msnm, 0, &cbUser_msnm );
1774 SQLBindParameter(hstmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_PASS_LEN, 0, pass, 0, &cbPass );
1775 SQLBindParameter(hstmt, 16, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &posts, 0, &cbPosts );
1776 SQLBindParameter(hstmt, 17, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &attachsig, 0, &cbAttachsig );
1777 SQLBindParameter(hstmt, 18, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &rank, 0, &cbRank );
1778 SQLBindParameter(hstmt, 19, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &level, 0, &cbLevel );
1779 SQLBindParameter(hstmt, 20, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_THEME_LEN, 0, theme, 0, &cbTheme );
1780 SQLBindParameter(hstmt, 21, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &timezone_offset, 0, &cbTimezone_offset );
1781 SQLBindParameter(hstmt, 22, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &last_login, 0, &cbLast_login );
1782 SQLBindParameter(hstmt, 23, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_UMODE_LEN, 0, umode, 0, &cbUmode );
1783 SQLBindParameter(hstmt, 24, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &uorder, 0, &cbUorder );
1784 SQLBindParameter(hstmt, 25, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &notify_method, 0, &cbNotify_method );
1785 SQLBindParameter(hstmt, 26, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &notify_mode, 0, &cbNotify_mode );
1786 SQLBindParameter(hstmt, 27, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_OCC_LEN, 0, user_occ, 0, &cbUser_occ );
1787 SQLBindParameter(hstmt, 28, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_BIO_LEN, 0, bio, 0, &cbBio );
1788 SQLBindParameter(hstmt, 29, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, ACCOUNT_USER_INTREST_LEN, 0, user_intrest, 0, &cbUser_intrest );
1789 SQLBindParameter(hstmt, 30, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &user_mailok, 0, &cbUser_mailok );
1790 SQLBindParameter(hstmt, 31, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &uid, 0, &cbUid );
1791
1792 strncpy2( (char*)uname, account -> getUname( ), ACCOUNT_UNAME_LEN );
1793 strncpy2( (char*)name, account -> getName( ), ACCOUNT_NAME_LEN );
1794 strncpy2( (char*)email, account -> getEmail( ), ACCOUNT_EMAIL_LEN );
1795 strncpy2( (char*)url, account -> getURL( ), ACCOUNT_URL_LEN );
1796 strncpy2( (char*)user_avatar, account -> getUserAvatar( ), ACCOUNT_USER_AVATAR_LEN );
1797 user_regdate = time( NULL );
1798 strncpy2( (char*)user_icq, account -> getUserIcq( ), ACCOUNT_USER_ICQ_LEN );
1799 strncpy2( (char*)user_from, account -> getUserFrom( ), ACCOUNT_USER_FROM_LEN );
1800 strncpy2( (char*)user_sig, account -> getUserSig( ), ACCOUNT_USER_SIG_LEN );
1801 user_viewemail = account -> getUserViewemail( );
1802 strncpy2( (char*)actkey, account -> getActkey( ), ACCOUNT_ACTKEY_LEN );
1803 strncpy2( (char*)user_aim, account -> getUserAim( ), ACCOUNT_USER_AIM_LEN );
1804 strncpy2( (char*)user_yim, account -> getUserYim( ), ACCOUNT_USER_YIM_LEN );
1805 strncpy2( (char*)user_msnm, account -> getUserMsnm( ), ACCOUNT_USER_MSNM_LEN );
1806 strncpy2( (char*)pass, account -> getPass( ), ACCOUNT_PASS_LEN );
1807 posts = account -> getPosts( );
1808 attachsig = account -> getAttachsig( );
1809 rank = account -> getRank( );
1810 level = account -> getLevel( );
1811 strncpy2( (char*)theme, account -> getTheme( ), ACCOUNT_THEME_LEN );
1812 timezone_offset = account -> getTimezoneOffset( );
1813 last_login = 0;
1814 strncpy2( (char*)umode, account -> getUmode( ), ACCOUNT_UMODE_LEN );
1815 uorder = account -> getUorder( );
1816 notify_method = account -> getNotifyMethod( );
1817 notify_mode = account -> getNotifyMode( );
1818 strncpy2( (char*)user_occ, account -> getUserOcc( ), ACCOUNT_USER_OCC_LEN );
1819 strncpy2( (char*)bio, account -> getBio( ), ACCOUNT_BIO_LEN );
1820 strncpy2( (char*)user_intrest, account -> getUserIntrest( ), ACCOUNT_USER_INTREST_LEN );
1821 user_mailok = account -> getUserMailok( );
1822 uid = account -> getUID( );
1823
1824 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
1825 SQLLEN count = 0;
1826 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1827 ret = RES_OK;
1828 }else{
1829 string s( "SQLRowCount in updateAccount sql=" );
1830 s += string( sql );
1831 setLastErrorString( s.c_str( ) );
1832 ret = RES_DB_QUERY_ERROR;
1833 }
1834 }else{
1835 string s( "SQLExecute in updateAccount 1 " );
1836 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1837 setLastErrorString( s.c_str( ) );
1838 ret = RES_DB_QUERY_ERROR;
1839 }
1840 }else{
1841 setLastErrorString( "SQLPrepare in updateAccount sql=" );
1842 ret = RES_ERROR;
1843 }
1844 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1845 hstmt = NULL;
1846 }else{
1847 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in updateAccount" );
1848 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1849 setLastErrorString( s.c_str( ) );
1850 ret = RES_ERROR;
1851 }
1852
1853 if( ret != RES_OK ){
1854 return ret;
1855 }
1856
1857 //xnpaccountのユーザテーブルに残りの情報を上書きする
1858 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1859 string sql;
1860
1861 sql = "UPDATE " + dbprefix + "_xnpaccount_users SET ";
1862 sql += "activate=?, ";
1863 sql += "address=?, ";
1864 sql += "division=?, ";
1865 sql += "tel=?, ";
1866 sql += "company_name=?, ";
1867 sql += "country=?, ";
1868 sql += "zipcode=?, ";
1869 sql += "fax=?, ";
1870 sql += "notice_mail=?, ";
1871 sql += "notice_mail_since=? ,";
1872 sql += "private_item_number_limit=" + unsignedIntToString( account -> getItemNumberLimit( ) ) + " ,";
1873 sql += "private_index_number_limit=" + unsignedIntToString( account -> getIndexNumberLimit( ) ) + " ,";
1874 sql += "private_item_storage_limit=" + doubleToString( account -> getItemStorageLimit( ) ) + " ";
1875 sql += "WHERE uid=?";
1876
1877 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
1878 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
1879 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &activate, 0, &cbActivate);
1880 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_ADDRESS_LEN, 0, address, 0, &cbAddress);
1881 SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_DIVISION_LEN, 0, division, 0, &cbDivision);
1882 SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_TEL_LEN, 0, tel, 0, &cbTel);
1883 SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_COMPANY_NAME_LEN, 0, company_name, 0, &cbCompany_name);
1884 SQLBindParameter(hstmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_COUNTRY_LEN, 0, country, 0, &cbCountry);
1885 SQLBindParameter(hstmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_ZIPCODE_LEN, 0, zipcode, 0, &cbZipcode);
1886 SQLBindParameter(hstmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_ACCOUNT_FAX_LEN, 0, fax, 0, &cbFax);
1887 SQLBindParameter(hstmt, 9, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &notice_mail, 0, &cbNotice_mail);
1888 SQLBindParameter(hstmt, 10, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &notice_mail_since, 0, &cbNotice_mail_since);
1889 SQLBindParameter(hstmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &uid, 0, &cbUid );
1890
1891 activate = account -> getActivate() ? 1 : 0;
1892 strncpy2( (char*)address, account -> getAddress( ) , XNP_ACCOUNT_ADDRESS_LEN );
1893 strncpy2( (char*)division, account -> getDivision(), XNP_ACCOUNT_DIVISION_LEN );
1894 strncpy2( (char*)tel, account -> getTel(), XNP_ACCOUNT_TEL_LEN );
1895 strncpy2( (char*)company_name, account -> getCompanyName(), XNP_ACCOUNT_COMPANY_NAME_LEN );
1896 strncpy2( (char*)country, account -> getCountry(), XNP_ACCOUNT_COUNTRY_LEN );
1897 strncpy2( (char*)zipcode, account -> getZipcode(), XNP_ACCOUNT_ZIPCODE_LEN );
1898 strncpy2( (char*)fax, account -> getFax(), XNP_ACCOUNT_FAX_LEN );
1899 notice_mail = account -> getNoticeMail( );
1900 notice_mail_since = account -> getNoticeMailSince( );
1901 uid = account -> getUID( );
1902
1903 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
1904 SQLLEN count = 0;
1905 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
1906 ret = RES_OK;
1907 }else{
1908 string s( "SQLRowCount in updateAccount sql=" );
1909 s += string( sql );
1910 setLastErrorString( s.c_str( ) );
1911 ret = RES_DB_QUERY_ERROR;
1912 }
1913 }else{
1914 string s( "SQLExecute in updateAccount 2 " );
1915 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1916 setLastErrorString( s.c_str( ) );
1917 ret = RES_DB_QUERY_ERROR;
1918 }
1919 }else{
1920 setLastErrorString( "SQLPrepare in updateAccount sql=" );
1921 ret = RES_ERROR;
1922 }
1923 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1924 }else{
1925 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in updateAccount" );
1926 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1927 setLastErrorString( s.c_str( ) );
1928 ret = RES_ERROR;
1929 }
1930 return ret;
1931 }
1932
1933 /**
1934 *
1935 * criteria_tで指定された範囲のユーザIDを返す.
1936 * ユーザIDの配列を確保してそこに書き込み,配列のアドレスを*uidsに書き込む.
1937 * 配列のサイズを*uidsLenに書き込む
1938 *
1939 * @param sid セッションID
1940 * @param cri 結果の範囲指定,ソート条件指定
1941 * @param uids ユーザのUIDの配列の出力先
1942 * @param uidsLen uids配列の要素数の出力先
1943 * @return RES_OK
1944 * @return RES_DB_NOT_INITIALIZED
1945 * @return RES_NO_SUCH_SESSION
1946 * @return RES_DB_QUERY_ERROR
1947 *
1948 */
1949 result_t dumpUids( sessionid_t sid, criteria_t* cri, userid_t** uids, int* uidsLen )
1950 {
1951 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
1952 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
1953
1954 result_t ret = RES_ERROR;
1955 userid_t* dst = 0;
1956 string sql;
1957 SQLRETURN sqlcode;
1958 SQLLEN count = 0;
1959
1960
1961 sql = "SELECT uid FROM " + dbprefix + "_xnpaccount_users ";
1962 sql += criteria2str( cri );
1963 if( countResultRows( sql.c_str(), &count ) == RES_OK ){
1964 *uidsLen = count;
1965 dst = new userid_t[ *uidsLen ];
1966 *uids = dst;
1967 }else{
1968 return RES_ERROR;
1969 }
1970 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
1971 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
1972 userid_t uid = 0;
1973 SQLLEN len = 0;
1974 SQLBindCol( hstmt, 1, SQL_C_ULONG, &uid, 0, &len );
1975
1976 for( int i = 0; ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS && i < *uidsLen ; i++ ){
1977 dst[ i ] = uid;
1978 }
1979
1980 syslog_printf( "dumpUids succeed" );
1981 ret = RES_OK;
1982 }else{
1983 string s( "SQLExecDirect in dumpUids " );
1984 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
1985 s += "sql=";
1986 s += string( sql );
1987 setLastErrorString( s.c_str( ) );
1988 syslog_printf( "dumpUids %s", getLastErrorString( ) );
1989 ret = RES_DB_QUERY_ERROR;
1990 }
1991 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
1992 }else{
1993 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in dumpUids" );
1994 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
1995 setLastErrorString( s.c_str( ) );
1996 syslog_printf( "dumpUids %s", getLastErrorString( ) );
1997 ret = RES_ERROR;
1998 }
1999 return ret;
2000 }
2001
2002 /**
2003 *
2004 * グループ数を返す.
2005 * 不正なセッションIDなら0を返す.
2006 *
2007 * @param sid セッションID
2008 * @return グループ数
2009 *
2010 */
2011 int getGroupCount( sessionid_t sid )
2012 {
2013 if( hdbc == NULL ) return 0;
2014 if( !isValidSessionID( sid ) ) return 0;
2015
2016 SQLRETURN sqlcode;
2017 SQLHANDLE hstmt = NULL;
2018 string sql;
2019 int ret = 0;
2020
2021 //グループ数を求める
2022 sql = "SELECT COUNT(*) FROM " + dbprefix + "_xnpaccount_groups";
2023 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2024 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2025 SQLUINTEGER count = 0;
2026 SQLLEN len = 0;
2027 SQLBindCol( hstmt, 1, SQL_C_ULONG, &count, 0, &len );
2028 if( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
2029 ret = count;
2030 }else {
2031 string s( "SQLFetch in getGroupCount sql=" );
2032 s += string( sql );
2033 setLastErrorString( s.c_str( ) );
2034 ret = 0;
2035 }
2036 }else{
2037 setLastErrorString( "SQLExecDirect in getGroupCount" );
2038 ret = 0;
2039 }
2040 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2041 }else{
2042 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in getGroupCount" );
2043 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2044 setLastErrorString( s.c_str( ) );
2045 ret = 0;
2046 }
2047 return ret;
2048 }
2049
2050 /**
2051 *
2052 * 所属グループ一覧取得.
2053 * ユーザが所属しているグループのIDを取得する
2054 *
2055 * @param sid セッションID
2056 * @param uid ユーザのUID
2057 * @param cri 結果の範囲指定,ソート条件指定
2058 * @param gids グループIDの配列の出力先
2059 * @param gidsLen gids配列の要素数の出力先
2060 * @return RES_DB_NOT_INITIALIZED
2061 * @return RES_NO_SUCH_SESSION
2062 * @return RES_NO_SUCH_USER
2063 * @return RES_DB_QUERY_ERROR
2064 * @return RES_OK
2065 *
2066 */
2067 result_t getGroupsByUid( sessionid_t sid, userid_t uid, criteria_t* cri, groupid_t** gids, int* gidsLen )
2068 {
2069 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2070 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2071 if( !uidExists( uid ) ) return RES_NO_SUCH_USER; //uidの存在をチェック
2072
2073 result_t ret = RES_ERROR;
2074 string sql;
2075 SQLRETURN sqlcode;
2076 SQLHANDLE hstmt = NULL;
2077 SQLLEN count = 0;
2078 groupid_t* dst = 0;
2079
2080 sql = "SELECT gid FROM " + dbprefix + "_xnpaccount_groups_users_link";
2081 sql += " WHERE uid=" + string( unsignedIntToString( uid ) );
2082 sql += criteria2str( cri );
2083 if( countResultRows( sql.c_str(), &count ) == RES_OK ){
2084 *gidsLen = count;
2085 dst = new groupid_t[ *gidsLen ];
2086 *gids = dst;
2087 }else{
2088 return RES_ERROR;
2089 }
2090
2091 //所属するグループの最大個数を求める
2092 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2093 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2094 if( count > 0 ){
2095 SQLHANDLE hstmt2 = NULL;
2096 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt2 ) ) == SQL_SUCCESS ) {
2097 sql = "SELECT gid, uid, is_admin FROM " + dbprefix + "_xnpaccount_groups_users_link";
2098 sql += " WHERE uid=" + string( unsignedIntToString( uid ) );
2099 sql += criteria2str( cri );
2100 if( ( sqlcode = SQLExecDirect( hstmt2, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2101 SQLLEN len = 0;
2102 groupid_t gid = 0;
2103 SQLBindCol( hstmt, 1, SQL_C_ULONG, &gid, 0, &len );
2104 for( int i = 0; ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS && i < *gidsLen ; i++ ){
2105 dst[ i ] = gid;
2106 }
2107 ret = RES_OK;
2108 }else{
2109 string s( "SQLExecDirect in getGroupsByUid " );
2110 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2111 s += string( ", sql=" ) + string( sql );
2112 setLastErrorString( s.c_str( ) );
2113 ret = RES_DB_QUERY_ERROR;
2114 }
2115 }else{
2116 string s( "SQLAllocHandle in getGroupsByUid " );
2117 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2118 setLastErrorString( s.c_str( ) );
2119 ret = RES_ERROR;
2120 }
2121 }else{
2122 ret = RES_OK;
2123 }
2124 }else{
2125 string s( "SQLExecDirect in getGroupsByUid " );
2126 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2127 s += string( ", sql=" ) + string( sql );
2128 setLastErrorString( s.c_str( ) );
2129 ret = RES_DB_QUERY_ERROR;
2130 }
2131 }else{
2132 string s( "SQLAllocHandle in getGroupsByUid " );
2133 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2134 setLastErrorString( s.c_str( ) );
2135 ret = RES_ERROR;
2136 }
2137 return ret;
2138 }
2139
2140 /**
2141 *
2142 * グループ管理権限問合せ.
2143 * ユーザにループの管理権限があるか(グループ管理者であるか)を問い合わせる.
2144 * ユーザやグループが存在しないなどの異常の場合,falseを返す.
2145 *
2146 * @param sid セッションID
2147 * @param gid グループのUID
2148 * @param uid ユーザのUID
2149 * @return true 管理権限あり
2150 * @return false 管理権限なし,または不明
2151 *
2152 */
2153 bool isGroupAdmin( sessionid_t sid, groupid_t gid, userid_t uid )
2154 {
2155 if( hdbc == NULL ) return false;
2156 if( !isValidSessionID( sid ) ) return false;
2157 if( !uidExists( uid ) ) return false;
2158 if( !gidExists( gid ) ) return false;
2159
2160 bool ret = false;
2161 string sql;
2162 SQLLEN count = 0;
2163
2164 sql = "SELECT * FROM " + dbprefix + "_xnpaccount_groups_users_link ";
2165 sql += "WHERE gid=" + string( unsignedIntToString( gid ) );
2166 sql += " AND uid=" + string( unsignedIntToString( uid ) );
2167 sql += " AND is_admin=1";
2168 if( countResultRows( sql.c_str(), &count ) == RES_OK ){
2169 if( count > 0 ){
2170 ret = true;
2171 }else{
2172 ret = false;
2173 }
2174 }else{
2175 ret = false;
2176 }
2177 return ret;
2178 }
2179
2180 /**
2181 *
2182 * グループID一覧.
2183 * 登録されているグループのID一覧を取得する.
2184 *
2185 * @param sid セッションID
2186 * @param cri 結果の範囲指定,ソート条件指定
2187 * @param gids グループIDの配列の出力先
2188 * @param gidsLen gids配列の要素数の出力先
2189 * @return RES_DB_NOT_INITIALIZED
2190 * @return RES_NO_SUCH_SESSION
2191 * @return RES_DB_QUERY_ERROR
2192 * @return RES_OK
2193 *
2194 */
2195 result_t dumpGids( sessionid_t sid, criteria_t* cri, groupid_t** gids, int* gidsLen )
2196 {
2197 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2198 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2199
2200 result_t ret = RES_ERROR;
2201 groupid_t* dst = 0;
2202 string sql;
2203 SQLRETURN sqlcode;
2204 SQLLEN count = 0;
2205
2206 sql = "SELECT gid FROM " + dbprefix + "_xnpaccount_groups ";
2207 sql += criteria2str( cri );
2208 if( countResultRows( sql.c_str(), &count ) == RES_OK ){
2209 *gidsLen = count;
2210 dst = new groupid_t[ *gidsLen ];
2211 *gids = dst;
2212 }else{
2213 return RES_ERROR;
2214 }
2215
2216 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2217 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2218 groupid_t gid = 0;
2219 SQLLEN len = 0;
2220 SQLBindCol( hstmt, 1, SQL_C_ULONG, &gid, 0, &len );
2221 for( int i = 0; ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS && i < *gidsLen ; i++ ){
2222 dst[ i ] = gid;
2223 }
2224
2225 ret = RES_OK;
2226 }else{
2227 string s( "SQLExecDirect in dumpGids " );
2228 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2229 s += "sql=";
2230 s += string( sql );
2231 setLastErrorString( s.c_str( ) );
2232 ret = RES_DB_QUERY_ERROR;
2233 }
2234 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2235 }
2236 return ret;
2237 }
2238
2239 /**
2240 *
2241 * グループ管理者IDを取得する.
2242 * あるグループの管理者のユーザIDを取得する.
2243 *
2244 * @param sid セッションID
2245 * @param gid 問い合わせるグループをIDで指定する
2246 * @param cri 結果の範囲指定,ソート条件指定
2247 * @param uids 管理者のUIDの配列を受け取るポインタ
2248 * @param uidsLen uids配列の要素数
2249 * @return RES_OK
2250 * @return RES_DB_NOT_INITIALIZED
2251 * @return RES_NO_SUCH_SESSION
2252 * @return RES_DB_QUERY_ERROR
2253 * @return RES_ERROR
2254 *
2255 */
2256 result_t dumpGroupAdmins( sessionid_t sid, groupid_t gid, criteria_t* cri, userid_t** uids, int* uidsLen )
2257 {
2258 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2259 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2260
2261 result_t ret = RES_ERROR;
2262 string sql;
2263 SQLRETURN sqlcode;
2264 SQLLEN count = 0;
2265
2266 sql = "SELECT uid FROM " + dbprefix + "_xnpaccount_groups_users_link ";
2267 sql += " WHERE is_admin=1 and gid=" + unsignedIntToString( gid );
2268 if( countResultRows( sql.c_str(), &count ) == RES_OK ){
2269 *uidsLen = count;
2270 *uids = new groupid_t[ *uidsLen ];
2271 }else{
2272 return RES_ERROR;
2273 }
2274 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2275 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2276 userid_t uid;
2277 SQLLEN len = 0;
2278 SQLBindCol( hstmt, 1, SQL_C_ULONG, &uid, 0, &len );
2279 for( int i = 0; ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS && i < *uidsLen ; i++ ){
2280 (*uids)[ i ] = uid;
2281 }
2282 ret = RES_OK;
2283 }else{
2284 string s( "SQLExecDirect in dumpGroupAdmins " );
2285 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2286 s += "sql=";
2287 s += string( sql );
2288 setLastErrorString( s.c_str( ) );
2289 ret = RES_DB_QUERY_ERROR;
2290 }
2291 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2292 }
2293 return ret;
2294 }
2295
2296 /**
2297 *
2298 * グループ所属ユーザ削除.
2299 * グループに所属するユーザを,グループから削除する.
2300 * デフォルトグループからは削除できない
2301 *
2302 * @param sid セッションID
2303 * @param gid どのグループから削除するかを指定するグループID
2304 * @param uid 削除対象のユーザのID
2305 * @return RES_DB_NOT_INITIALIZED
2306 * @return RES_NO_SUCH_SESSION
2307 * @return RES_NO_SUCH_USER
2308 * @return RES_NO_SUCH_GROUP
2309 * @return RES_DB_QUERY_ERROR
2310 * @return RES_OK
2311 * @return RES_ERROR
2312 *
2313 */
2314 result_t deleteMember( sessionid_t sid, groupid_t gid, userid_t uid )
2315 {
2316 if( gid == group_t::GID_DEFAULT ) return RES_ERROR;
2317 return deleteMemberNoLimit( sid, gid, uid );
2318 }
2319
2320 /**
2321 *
2322 * グループ所属ユーザ削除.
2323 * グループに所属するユーザを,グループから削除する.
2324 * デフォルトグループからも削除できる点が,deleteMemberと異なる
2325 *
2326 * @param sid セッションID
2327 * @param gid どのグループから削除するかを指定するグループID
2328 * @param uid 削除対象のユーザのID
2329 * @return RES_DB_NOT_INITIALIZED
2330 * @return RES_NO_SUCH_SESSION
2331 * @return RES_NO_SUCH_USER
2332 * @return RES_NO_SUCH_GROUP
2333 * @return RES_DB_QUERY_ERROR
2334 * @return RES_OK
2335 * @return RES_ERROR
2336 *
2337 */
2338 static result_t deleteMemberNoLimit( sessionid_t sid, groupid_t gid, userid_t uid )
2339 {
2340 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2341 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2342 if( !uidExists( uid ) ) return RES_NO_SUCH_USER; //uidの存在をチェック
2343 if( !gidExists( gid ) ) return RES_NO_SUCH_GROUP; //gidの存在をチェック
2344
2345 result_t ret = RES_ERROR;
2346 string sql;
2347 SQLRETURN sqlcode;
2348 SQLHANDLE hstmt = NULL;
2349
2350 sql = "DELETE FROM " + dbprefix + "_xnpaccount_groups_users_link ";
2351 sql += "WHERE gid=" + string( unsignedIntToString( gid ) );
2352 sql += " AND uid=" + string( unsignedIntToString( uid ) );
2353 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2354 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2355 SQLLEN count = 0;
2356 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
2357 ret = RES_OK;
2358 }else{
2359 string s( "SQLRowCount in deleteMember" );
2360 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2361 s += string( ", sql=" ) + string( sql );
2362 setLastErrorString( s.c_str( ) );
2363 ret = RES_NO_SUCH_USER;
2364 }
2365 }else{
2366 string s( "SQLExecDirect in deleteMember" );
2367 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2368 s += ", sql=";
2369 s += string( sql );
2370 setLastErrorString( s.c_str( ) );
2371 ret = RES_DB_QUERY_ERROR;
2372 }
2373 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2374 }else{
2375 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in deleteMember" );
2376 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2377 setLastErrorString( s.c_str( ) );
2378 ret = RES_ERROR;
2379 }
2380 return ret;
2381 }
2382
2383 /**
2384 *
2385 * グループ所属ユーザ追加.
2386 * グループのメンバーにユーザを追加する.
2387 *
2388 * @param sid セッションID
2389 * @param gid 所属先グループのID
2390 * @param uid 所属させるユーザのID
2391 * @param admin 管理者権限を与えるならtrue
2392 * @return RES_OK
2393 * @return RES_DB_NOT_INITIALIZED
2394 * @return RES_NO_SUCH_SESSION
2395 * @return RES_NO_SUCH_USER
2396 * @return RES_NO_SUCH_GROUP
2397 * @return RES_DB_QUERY_ERROR
2398 *
2399 */
2400 result_t insertMember( sessionid_t sid, groupid_t gid, userid_t uid, bool admin )
2401 {
2402 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2403 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2404 if( !uidExists( uid ) ) return RES_NO_SUCH_USER; //uidの存在をチェック
2405 if( !gidExists( gid ) ) return RES_NO_SUCH_GROUP; //gidの存在をチェック
2406
2407 result_t ret = RES_ERROR;
2408 string sql;
2409 SQLRETURN sqlcode;
2410
2411 //メンバーを追加
2412 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2413 sql = "INSERT INTO " + dbprefix + "_xnpaccount_groups_users_link ( gid, uid, is_admin ) VALUES (";
2414 sql += string( unsignedIntToString( gid ) ) + ", ";
2415 sql += string( unsignedIntToString( uid ) ) + ", ";
2416 sql += string( admin ? "1" : "0" ) + ") ";
2417 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2418 SQLLEN count = 0;
2419 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
2420 ret = RES_OK;
2421 }else{
2422 string s( "SQLRowCount in insertMember " );
2423 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2424 s += string( ", sql=" ) + string( sql );
2425 setLastErrorString( s.c_str( ) );
2426 ret = RES_DB_QUERY_ERROR;
2427 }
2428 }else{
2429 string s( "SQLExecDirect in insertMember " );
2430 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2431 s += string( ", sql=" ) + string( sql );
2432 setLastErrorString( s.c_str( ) );
2433 ret = RES_DB_QUERY_ERROR;
2434 }
2435 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2436 }else{
2437 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in insertMember" );
2438 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2439 setLastErrorString( s.c_str( ) );
2440 ret = RES_ERROR;
2441 }
2442 return ret;
2443 }
2444
2445 /**
2446 *
2447 * グループ所属ユーザ取得.
2448 * あるグループの所属しているユーザのユーザIDを取得する
2449 *
2450 * @param sid セッションID
2451 * @param gid どのグループの所属ユーザを問い合わせるかをグループをIDで指定
2452 * @param cri 結果の範囲指定,ソート条件指定
2453 * @param uids 所属ユーザのUIDの配列を受け取るポインタ
2454 * @param uidsLen uids配列の要素数
2455 * @return RES_OK
2456 * @return RES_DB_NOT_INITIALIZED
2457 * @return RES_NO_SUCH_SESSION
2458 * @return RES_NO_SUCH_GROUP
2459 * @return RES_DB_QUERY_ERROR
2460 * @return RES_ERROR
2461 *
2462 */
2463 result_t getMembers( sessionid_t sid, groupid_t gid, criteria_t* cri, userid_t** uids, int* uidsLen )
2464 {
2465 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2466 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2467 if( !gidExists( gid ) ) return RES_NO_SUCH_GROUP; //gidの存在をチェック
2468
2469 result_t ret = RES_ERROR;
2470 string sql;
2471 SQLRETURN sqlcode;
2472 SQLHANDLE hstmt = NULL;
2473 userid_t* dst = 0;
2474
2475 //how many members ?
2476 sql = "SELECT COUNT(*) FROM " + dbprefix + "_xnpaccount_groups_users_link ";
2477 sql += " WHERE gid=" + string( unsignedIntToString( gid ) );
2478 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2479 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2480 SQLUINTEGER count = 0;
2481 SQLLEN len = 0;
2482 SQLBindCol( hstmt, 1, SQL_C_ULONG, &count, 0, &len );
2483 if( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){
2484 dst = new userid_t[ count ];
2485 *uids = dst;
2486 *uidsLen = count;
2487 if( count > 0 ){
2488 //retrieve member's IDs
2489 SQLHANDLE hstmt2 = NULL;
2490 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt2 ) ) == SQL_SUCCESS ) {
2491 sql = "SELECT uid, gid, is_admin FROM " + dbprefix + "_xnpaccount_groups_users_link ";
2492 sql += " WHERE gid=" + string( unsignedIntToString( gid ) );
2493 sql += " " + string( criteria2str( cri ) );
2494 if( ( sqlcode = SQLExecDirect( hstmt2, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2495 SQLUINTEGER uid = 0;
2496 SQLLEN len = 0;
2497 SQLBindCol( hstmt2, 1, SQL_C_ULONG, &uid, 0, &len );
2498 for( SQLUINTEGER i = 0; ( sqlcode = SQLFetch( hstmt2 ) ) == SQL_SUCCESS && i < count ; i++ ){
2499 dst[ i ] = uid;
2500 }
2501 ret = RES_OK;
2502 }else{
2503 setLastErrorString( "SQLExecDirect in getMembers" );
2504 ret = RES_DB_QUERY_ERROR;
2505 }
2506 SQLFreeHandle( SQL_HANDLE_STMT, hstmt2 );
2507 }else{
2508 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in getMembers" );
2509 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2510 setLastErrorString( s.c_str( ) );
2511 ret = RES_ERROR;
2512 }
2513 }else{
2514 ret = RES_OK;
2515 }
2516 }else{
2517 string s( "SQLFetch in getMembers sql=" );
2518 s += string( sql );
2519 setLastErrorString( s.c_str( ) );
2520 ret = RES_DB_QUERY_ERROR;
2521 }
2522 }else{
2523 setLastErrorString( "SQLExecDirect in getMembers" );
2524 ret = RES_DB_QUERY_ERROR;
2525 }
2526 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2527 }else{
2528 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in getMembers" );
2529 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2530 setLastErrorString( s.c_str( ) );
2531 ret = RES_ERROR;
2532 }
2533 return ret;
2534 }
2535
2536 /**
2537 *
2538 * グループの削除.
2539 * データベースからグループを削除します.
2540 *
2541 * @param sid セッションID
2542 * @param gid どのグループの所属ユーザを問い合わせるかをグループをIDで指定
2543 * @return RES_OK
2544 * @return RES_DB_QUERY_ERROR
2545 * @return RES_NO_SUCH_SESSION
2546 * @return RES_DB_NOT_INITIALIZED
2547 *
2548 */
2549 result_t deleteGroup( sessionid_t sid, groupid_t gid )
2550 {
2551 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2552 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2553
2554 result_t ret = RES_ERROR;
2555 string sql;
2556 SQLRETURN sqlcode;
2557 SQLHANDLE hstmt = NULL;
2558
2559 sql = "DELETE FROM " + dbprefix + "_xnpaccount_groups ";
2560 sql += "WHERE gid = " + string( unsignedIntToString( gid ) );
2561 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2562 if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){
2563 SQLLEN count = 0;
2564 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
2565 ret = RES_OK;
2566 }else{
2567 string s( "SQLRowCount in deleteGroup" );
2568 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2569 s += string( ", sql=" ) + string( sql );
2570 setLastErrorString( s.c_str( ) );
2571 ret = RES_NO_SUCH_USER;
2572 }
2573 }else{
2574 string s( "SQLExecDirect in deleteGroup" );
2575 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2576 s += ", sql=";
2577 s += string( sql );
2578 setLastErrorString( s.c_str( ) );
2579 ret = RES_DB_QUERY_ERROR;
2580 }
2581 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2582 }else{
2583 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in deleteGroup" );
2584 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2585 setLastErrorString( s.c_str( ) );
2586 ret = RES_ERROR;
2587 }
2588 return ret;
2589 }
2590
2591 /**
2592 *
2593 * グループ登録.
2594 * グループの情報をデータベースに記録する.
2595 * 登録したグループに対応するグループIDをgidに格納する.
2596 *
2597 * @param sid セッションID
2598 * @param group 登録したいグループの情報
2599 * @param gid 登録したグループに対応するグループID
2600 * @return RES_OK
2601 * @return RES_DB_NOT_INITIALIZED
2602 * @return RES_NO_SUCH_SESSION
2603 * @return RES_DB_QUERY_ERROR
2604 *
2605 */
2606 result_t insertGroup( sessionid_t sid, const group_t* group, groupid_t* gid )
2607 {
2608 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2609 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2610
2611 result_t ret = RES_ERROR;
2612 string sql;
2613 SQLCHAR gname[XNP_GROUP_GNAME_LEN+1], gdesc[XNP_GROUP_GDESC_LEN+1];
2614 SQLINTEGER item_number_limit;
2615 SQLINTEGER index_number_limit;
2616 SQLDOUBLE item_storage_limit;
2617 SQLLEN cbGname = SQL_NTS, cbGdesc = SQL_NTS, cbItem_number_limit = 0, cbIndex_number_limit = 0, cbItem_storage_limit = 0;
2618 SQLRETURN sqlcode;
2619
2620 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2621 sql = "INSERT INTO " + dbprefix + "_xnpaccount_groups ( gname, gdesc, group_item_number_limit, group_index_number_limit, group_item_storage_limit ) VALUES ( ?, ?, ?, ?, ? )";
2622 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
2623 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
2624 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_GROUP_GNAME_LEN, 0, gname, 0, &cbGname );
2625 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_GROUP_GDESC_LEN, 0, gdesc, 0, &cbGdesc );
2626 SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &item_number_limit, 0, &cbItem_number_limit);
2627 SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &index_number_limit, 0, &cbIndex_number_limit);
2628 SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &item_storage_limit, 0, &cbItem_storage_limit);
2629 strncpy2( (char*)gname, group -> getGname( ), XNP_GROUP_GNAME_LEN );
2630 strncpy2( (char*)gdesc, group -> getDesc( ), XNP_GROUP_GDESC_LEN );
2631 item_number_limit = group -> getItemNumberLimit( );
2632 index_number_limit = group -> getIndexNumberLimit( );
2633 item_storage_limit = group -> getItemStorageLimit( );
2634 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
2635 SQLLEN count = 0;
2636 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
2637 //グループIDを取得する
2638 if( dbtype == DBTYPE_MYSQL ){
2639 sql = "SELECT LAST_INSERT_ID()";
2640 }else if( dbtype == DBTYPE_SQLITE ){
2641 sql = "SELECT LAST_INSERT_ROWID()";
2642 }
2643 ret = queryGetUnsignedInt( "insertGroup", sql, (unsigned int*)gid );
2644 }else{
2645 string s( "SQLRowCount in insertGroup sql=" );
2646 s += string( sql );
2647 setLastErrorString( s.c_str( ) );
2648 ret = RES_DB_QUERY_ERROR;
2649 }
2650 }else{
2651 string s( "SQLExecute in insertGroup " );
2652 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2653 setLastErrorString( s.c_str( ) );
2654 ret = RES_DB_QUERY_ERROR;
2655 }
2656 }else{
2657 string s( "SQLPrepare in insertGroup " );
2658 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2659 setLastErrorString( s.c_str( ) );
2660 ret = RES_ERROR;
2661 }
2662 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2663 }else{
2664 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in insertGroup" );
2665 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2666 setLastErrorString( s.c_str( ) );
2667 ret = RES_ERROR;
2668 }
2669
2670 //
2671 if ( ret == RES_OK ){
2672 //group indexを作成
2673
2674 //group index用のsort_num生成
2675 string sql = "SELECT MAX(sort_number) FROM " +
2676 dbprefix + "_xnpaccount_index WHERE parent_index_id=" + unsignedIntToString(item::IID_ROOT) +
2677 " AND (open_level=" + unsignedIntToString(index::OL_GROUP_ONLY) +
2678 " OR open_level=" + unsignedIntToString(index::OL_PUBLIC) + ")";
2679 unsigned int sortNumber;
2680 ret = queryGetUnsignedInt( "insertGroup", sql, &sortNumber );
2681 sortNumber++;
2682 if ( ret == RES_OK ){
2683 // group index作成
2684 index_t index;
2685 userid_t uid;
2686 ret = sessionID2UID( sid, &uid );
2687 if ( ret == RES_OK ){
2688 index.setItemTypeID(item::ITID_INDEX);
2689 index.setContributorUID(uid);
2690 index.setParentIndexID(item::IID_ROOT);
2691 index.setOwnerGID(*gid);
2692 index.setOpenLevel(index::OL_GROUP_ONLY);
2693 index.setSortNumber(sortNumber);
2694 index.setTitle(group->getGname());
2695 indexid_t groupXID;
2696 ret = insertIndexInternal( sid, &index, &groupXID );
2697 if ( ret == RES_OK ){
2698 // xnpaccuont_groupsのgroup_index_idの書き換え
2699 sql = "UPDATE " + dbprefix + "_xnpaccount_groups SET group_index_id="
2700 + unsignedIntToString(groupXID) + " WHERE gid=" + unsignedIntToString(*gid);
2701 ret = querySimple( "insertGroup", sql );
2702 }
2703 }
2704 }
2705 }
2706
2707 return ret;
2708 }
2709
2710 /**
2711 *
2712 * グループ情報を変更する
2713 *
2714 * @param sid セッションID
2715 * @param group 新しいグループ情報
2716 * @return RES_OK
2717 * @return RES_ERROR
2718 * @return RES_DB_NOT_INITIALIZED
2719 * @return RES_NO_SUCH_SESSION
2720 * @return RES_NO_SUCH_GROUP
2721 * @return RES_DB_QUERY_ERROR
2722 *
2723 */
2724 result_t updateGroup( sessionid_t sid, const group_t* group )
2725 {
2726 if( hdbc == NULL ) return RES_DB_NOT_INITIALIZED;
2727 if( group == NULL ) return RES_ERROR;
2728 if( !isValidSessionID( sid ) ) return RES_NO_SUCH_SESSION;
2729 if( !gidExists( group -> getGID( ) ) ) return RES_NO_SUCH_GROUP;
2730
2731 result_t ret = RES_ERROR;
2732 string sql;
2733 SQLCHAR gname[XNP_GROUP_GNAME_LEN+1], gdesc[XNP_GROUP_GDESC_LEN+1];
2734 SQLLEN cbGname = SQL_NTS, cbGdesc = SQL_NTS;
2735 SQLRETURN sqlcode;
2736
2737 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2738 sql = "UPDATE " + dbprefix + "_xnpaccount_groups SET gname=?, gdesc=?, ";
2739 sql += "group_item_number_limit=" + unsignedIntToString( group -> getItemNumberLimit( ) ) + " ,";
2740 sql += "group_index_number_limit=" + unsignedIntToString( group -> getIndexNumberLimit( ) ) + " ,";
2741 sql += "group_item_storage_limit=" + doubleToString( group -> getItemStorageLimit( ) ) + " ";
2742 sql += "WHERE gid=" + string( unsignedIntToString( group -> getGID( ) ) );
2743 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
2744 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
2745 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_GROUP_GNAME_LEN, 0, gname, 0, &cbGname );
2746 SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_GROUP_GDESC_LEN, 0, gdesc, 0, &cbGdesc );
2747 strncpy2( (char*)gname, group -> getGname( ), XNP_GROUP_GNAME_LEN );
2748 strncpy2( (char*)gdesc, group -> getDesc( ), XNP_GROUP_GDESC_LEN );
2749 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
2750 SQLLEN count = 0;
2751 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
2752 ret = RES_OK;
2753 }else{
2754 string s( "SQLRowCount in updateGroup sql=" );
2755 s += string( sql );
2756 setLastErrorString( s.c_str( ) );
2757 ret = RES_DB_QUERY_ERROR;
2758 }
2759 }else{
2760 string s( "SQLExecute in updateGroup " );
2761 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2762 setLastErrorString( s.c_str( ) );
2763 ret = RES_DB_QUERY_ERROR;
2764 }
2765 }else{
2766 setLastErrorString( "SQLPrepare in updateGroup sql=" );
2767 ret = RES_ERROR;
2768 }
2769 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2770 }else{
2771 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in updateGroup" );
2772 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2773 setLastErrorString( s.c_str( ) );
2774 ret = RES_ERROR;
2775 }
2776
2777 if( ret == RES_OK ){
2778 // updateすべきindex_idを得る
2779 sql = "SELECT group_index_id from " + dbprefix + "_xnpaccount_groups as tg "
2780 " left join " + dbprefix + "_xnpaccount_item_basic as ti on tg.group_index_id = ti.item_id "
2781 " left join " + dbprefix + "_xnpaccount_index as tx on ti.item_id = tx.index_id "
2782 " where tg.gid=" + unsignedIntToString(group->getGID()) +
2783 " and ti.item_type_id=" + unsignedIntToString(item::ITID_INDEX) +
2784 " and tx.parent_index_id=" + unsignedIntToString(item::IID_ROOT);
2785 indexid_t xid;
2786 ret = queryGetUnsignedInt( "updateGroup", sql, &xid );
2787
2788 if ( ret == RES_OK ){
2789 if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) {
2790 sql = "UPDATE " + dbprefix + "_xnpaccount_item_basic set title=? "
2791 "WHERE item_id=" + unsignedIntToString(xid);
2792 sqlcode = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
2793 if( sqlcode == SQL_SUCCESS || sqlcode == SQL_SUCCESS_WITH_INFO ){
2794 cbGname = SQL_NTS;
2795 SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, XNP_GROUP_GNAME_LEN, 0, gname, 0, &cbGname );
2796 strncpy2( (char*)gname, group -> getGname( ), XNP_GROUP_GNAME_LEN );
2797 if( ( sqlcode = SQLExecute( hstmt ) ) == SQL_SUCCESS ){
2798 SQLLEN count = 0;
2799 if( ( sqlcode = SQLRowCount( hstmt, &count ) ) == SQL_SUCCESS && count > 0 ){
2800 ret = RES_OK;
2801 }else{
2802 string s( "SQLRowCount in updateGroup sql=" );
2803 s += string( sql );
2804 setLastErrorString( s.c_str( ) );
2805 ret = RES_DB_QUERY_ERROR;
2806 }
2807 }else{
2808 string s( "SQLExecute in updateGroup " );
2809 s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode );
2810 setLastErrorString( s.c_str( ) );
2811 ret = RES_DB_QUERY_ERROR;
2812 }
2813 }else{
2814 setLastErrorString( "SQLPrepare in updateGroup sql=" );
2815 ret = RES_ERROR;
2816 }
2817 SQLFreeHandle( SQL_HANDLE_STMT, hstmt );
2818 }else{
2819 string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in updateGroup" );
2820 s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode );
2821 setLastErrorString( s.c_str( ) );
2822 ret = RES_ERROR;
2823 }
2824 }
2825 }
2826 return RES_OK;
2827 }
2828
2829 /**
2830 *
2831