SEED PHP 파일은 http://seed.kisa.or.kr/iwt/ko/index.do 에 가면 있다.

KISA 사이트는 소스가 PHP 인지 JSP 인지 식별이 어렵게 do 라는 확장자를 사용했다는 걸 알 수 있다.


알림마당 -> 자료실에서 PHP 버전을 찾아서 다운로드 받을 수 있다.

http://seed.kisa.or.kr/iwt/ko/bbs/EgovReferenceList.do?bbsId=BBSMSTR_000000000002


   [암호화 및 복호화 과정]


SEED는 128비트의 암⋅복호화키를 이용하여 임의의 길이를 갖는 입력 메시지를 128비트의 블록단위로 처리하는 128비트 블록암호 알고리즘이다. 따라서 임의의 길이를 가지는 평문 메시지를 128비트씩 블록단위로 나누어 암호화하여 암호문을 생성한다.


예제를 실행해보니 복호화가 제대로 안된다.

이걸 일일이 분석해볼 시간도 없고 능력도 안되어서 바로 포기했다.


그리고 구글링해서 다른 걸 찾아냈다.

http://qnibus.com/blog/how-to-use-seed128-for-php/

https://github.com/qnibus/seed128/


class.seed.php 파일을 만든 분의 사이트에 가서 class.seed.php 파일 내용을 수정하라고 나온다.


필요한 파일 class.crypto.php, class.seed.php 2개를 폴더에 복사 및 수정해서 소스 디렉토리에 저장한다.


사용법

ㅇ class.crypto.php 파일 내에 있는 $pbUserKey 값은 수정해서 사용한다.

ㅇ $IV 값도 수정해서 사용한다.


<?php
    include 'phpclass/class.crypto.php';
    $crypto = new Crypto(); // 암호화 객체 생성
    $text ='암호화할 문장을 여기에 적어주시면 됩니다.';
    $enc = $crypto->encrypt($text);
    echo $enc.'<br /> 원문 길이 : '.strlen($text).'  암호화 길이 : '.strlen($enc).'<br />';
    $dec = $crypto->decrypt($enc);
    echo $dec;
?>


평문($text)의 길이가 길면 비례해서 암호문의 길이도 길어진다.

그러므로 DB column 설계시 고려해서 해야 한다.

개인정보인 전화번호를 암호화 저장하는게 안전할 거 같아서 테스트를 해보니 암호화시 32 bytes 가 된다.

DB에 암호화 저장하고 화면에 보여줄 때 복호화해서 보여주면 된다.


Android 와 연동해서 테스트는 아직 안해봤다.


728x90
블로그 이미지

Link2Me

,

jQuery dialog (jQuery 팝업)창을 띄우는 코드를 사용하려면 https://jqueryui.com/dialog/ 사이트를 참조하면 된다.


$("#id").dialog() - 해당 id로 지정된 영역의 내용을 다이얼로그로 생성
$("#id").dialog("open")  - 다이얼로그 오픈
$("#id").dialog("close") - 다이얼로그를 화면상에서 보이지 않게함
$("#id").dialog("isOpen") - 해당 id를 가진 다이얼로그가 열려진 상태인 경우 true값
$("#id").dialog("moveToTop") - 다이얼로그를 최상위로 배치


- autoOpen : 페이지 로드시 자동으로 다이얼로그 열리는 것을 막고자 할 때 사용 ex) autoOpen:false

- modal : 페이지의 다른 내용위에 최상위로 표시되면서 다른 영역은 선택할수 없도록 할 때 사용 ex) modal:true

- width, height : 다이얼로그 창의 너비, 높이를 설정



아래 파일 구조는 http://link2me.tistory.com/1098 게시글과 같이 보면 이해가 될 것이다.

기본적인 Layout 에서 팝업창으로 새 그룹을 생성하고 바로 화면을 갱신처리하는 일련의 코드이다.


    <div data-role="footer" data-position="fixed" data-theme="d">
        <table>
        <tr>
        <td width="15%"></td>
        <td width="70%" align=center>그룹 추가</td>
        <td width="15%" align=right><a href="#" data-role="button" data-icon="plus" data-iconpos="left" id="groupadd">추가</a></td>
        </tr>
        </table>       
    </div>
</div>
<div id="dialog-add" title="그룹 추가">
    <form>
        <p>새 그룹명</p>
        <input type="text" name="group" />
        <input type="hidden" name="uid" value='<?php echo $uid?>' />
        <input type="hidden" name="status" value='n' />
    </form>
</div>


추가 버튼(id="groupadd")을 누르면 dialog 창이 떠서 새 그룹명을 입력 받고 처리하도록 하고 싶다면??


먼저 jQuery 를 추가해야 한다.

https://jqueryui.com/dialog/ 사이트를 참조해서 아래 색깔로 표시된 것을 복사하여 붙여넣기 한다.


<link href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="js/group_dialog.js"></script> <!-- 작성할 jQuery 스크립트 -->


===== group_dialog.js ======

$(function(){
    $("#dialog-add").dialog({
        autoOpen: false,
        buttons:[
            {
                text: "추가",
                click: function(){
                    var uid = $("input[name='uid']").val();
                    var group = $("input[name='group']").val();                   
                    if(!group) { // 입력 여부 검사
                        alert("그룹명을 입력하세요");
                        $("input[name='group']").focus();
                        return false;
                    }
                    var status = $("input[name='status']").val();
                    GroupAdd(uid,group,status);
                }
            },
            {
                text: "취소",
                click: function(){
                    $(this).dialog("close");
                }
            }
        ]
    });

    $("#groupadd").click(function(){       
        $("#dialog-add").dialog("open");
    });

});

function GroupAdd(uid,group,status){
    $.post("GroupMake.php", {uid:uid, group:group,status:status}, function(msg){
        if(msg==1){
            location.reload(); // 화면 갱신처리 (같은 화면을 갱신처리하는 것임)          
        } else if(msg==0){
            alert('그룹 추가에 실패했습니다');
        } else if(msg=='-1'){
            alert('그룹이 이미 존재합니다');
        } else if(msg=='-2'){
            alert('DB 에러가 발생했습니다');
        }
        $("#dialog-add").dialog("close");
    });
}



======= GroupMake.php =====

바로 접속하는 걸 방지하는 코드는 생략했다. 간편하게 내용 중심으로 작성해두기 위해서....

<?php
include ('dbconnect.php');
require_once "class/GroupClass.php";
$c=new GroupClass;

if(strcmp($_REQUEST['status'],'n')==0){//추가   
    $rs=$c->NewGroup($_REQUEST['uid'],$group); // 즐겨찾기 그룹명 추가
    // rs : 1(성공), 0(실패), -1(중복), -2(DB error)
} else if (strcmp($_REQUEST['status'],'d')==0){//삭제
    $rs=$c->DelGroup($_REQUEST['uid'],$group);
    // rs : 1(성공), 0(실패)
}
echo $rs;  // jQuery 의
function(msg) 로 던져지는 결과값
?>


개념을 설명하는 자료이므로 class/GroupClass.php 파일 내용은 적지 않는다.

이 정도면 봐도 충분히 응용이 가능하다고 본다.


참고하면 도움되는 게시글 링크

https://www.oreilly.com/library/view/jquery-ui/9781449325176/ch04s05.html



728x90
블로그 이미지

Link2Me

,

mysql_num_rows() 함수는 데이터베이스에서 쿼리를 날려서 나온 레코드들의 갯수를 카운트할 때 사용한다.
값이 없으면 0, 값이 있으면 레코드 갯수를 반환한다.

function MemberInfoView($id,$pw){
    global $db;
    $query="select * from member ";
    $query.="where userID='".$id."' and passwd=md5('".$pw."')";
   
    if($result=mysql_query($query)){
        $cnt=mysql_num_rows($result); // 개수 반환
        if($cnt==1) {
            $row=mysql_fetch_array($result);
            return $row;
        } else {
            return $cnt;
        }
       
    } else {
        return 0;
    }
}


mysql_num_fields($result); // 칼럼의 개수를 구할 때 사용

728x90
블로그 이미지

Link2Me

,

로그인 체크함수다.

Web에서 로그인하는 경우와 안드로이드에서 로그인하는 경우 2가지를 모두 수용할 수 있게 작성했다.

안드로이드폰 직접 접속시에는 폰의 장치정보를 인식하므로 deviceID 정보를 식별자로 사용하여 Web 접속과 Mobile 접속을 구분 처리했다.


<?php
if(!isset($_SESSION)) {
    session_start();
}
if(isset($_POST['loginID']) && !empty($_POST['loginID']) && isset($_POST['loginPW']) && !empty($_POST['loginPW'])) {
    $loginID = trim($_POST['loginID']);
    $loginPW = trim($_POST['loginPW']);
    $deviceID = trim($_POST['deviceID']);

    $deviceID = $deviceID ? $deviceID : '';

    if(empty($deviceID)){
        require_once 'dbconnect.php'; // db접속
        require_once 'phpclass/loginClass.php';

        $c=new LoginClass();

        $row = $c->WebUserAuthCheck($loginID,$loginPW);
        if(is_array($row)) {
            if($row['code'] > 0) {
                $_SESSION['userID'] = $row['id'];
                $_SESSION['userPW'] = md5($loginPW);
                $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
                $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];

                echo("<meta http-equiv='Refresh' content='0; URL=list.php'>");
            } else {
                echo '권한 불가';
            }
        } else if($row == '0'){
            $msg ='정보가 올바르지 않습니다';
            echo "<script>alert('".$msg."');history.go(-1);</script>";
        } else {
            $msg ='정보가 올바르지 않습니다';
            echo "<script>alert('".$msg."');history.go(-1);</script>";
        }

    } else {
        require_once 'db.info.php';
        require_once 'phpclass/dbClass.php';
        $conn=new MySQLDbClass();
        $DB_CONNECT = $conn->isConnectDb($DB); // 안드로이드폰에서는 반드시 객체로 생성해야 정상접속
        require_once 'phpclass/loginClass.php';
        $c=new LoginClass();

        $result = $c->MobileUserAuthCheck($loginID,$loginPW,$deviceID);
        if($result > 0 ) {
            session_save_path('./_tmp/session');

            $_SESSION['userID'] = $loginID;
            $_SESSION['userPW'] = md5($loginPW);
            $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
            $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];
            echo 'Login Success';
        } else if($result == 0) {
            echo 'Login Fail';
        } else {
            echo 'Phone Dismatch';
        }
    }
   
} else {
    echo("<meta http-equiv='Refresh' content='0; URL=loginForm.php'>");
}
?>


728x90
블로그 이미지

Link2Me

,

배열이 아닌 것을 배열 변수로 만들어서 검색결과를 알고 싶은 경우가 있다.

검색조건(search_item) 은 이름, 전화번호, 부서명 등으로 지정하고

검색어를 넣어서 배열에서 검색결과 처리를 하고자 할 경우 로직의 예이다.


첫번째 행의 변수는 $search[0] 로 할당하고, 두번째 행

$search_keyword = isset($_REQUEST['searchValue']) ? urldecode($_REQUEST['searchValue']) : '';


$search[1] = isset($_REQUEST['searchValue']) ? urldecode($_REQUEST['searchValue']) : '';

로 하면 배열 선언이 없는 상태라서 에러가 발생한다.


이렬 경우 보통은

php.ini 에서

error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE

로 처리하라고 되어 있다.

개발하면서 이 옵션은

error_reporting = E_ALL

로 설정해서 개발을 해야 에러가 발생하는 부분을 전부 화면에 표시를 해주므로 로직상의 문제점을 제거하면서 개발을 할 수 있다.


$search_item = isset($_REQUEST['searchName']) ? $_REQUEST['searchName'] : '';
$search_keyword = isset($_REQUEST['searchValue']) ? urldecode($_REQUEST['searchValue']) : '';

if(strlen($search_keyword) == 0){  // 입력값이 없으면 목록 없음 출력
    echo '<li data-icon="false">';
    echo '<a href="#">목록이 없습니다</a>';
    echo '</li>';
} else {
    // 검색어 값이 존재하면 배열 변수로 저장

    $search = array($search_item,$search_keyword);


    $c=new MemberClass;
    $rs=$c->MemberSearch($search);

    if($rs==0){    // 검색결과가 없으면
        echo '<li data-icon="false">';
        echo '<a href="#">목록이 없습니다.</a>';
        echo '</li>';

    } else { // 검색결과가 있으면
        // 검색결과 처리
    }

}


728x90
블로그 이미지

Link2Me

,

PHP 에서 MySQL 을 접속하고 DB 작업을 편리하게 하는 함수이다.

킴스큐 RB 빌더는 DB 접속 등 함수화를 해서 편하게 코딩하게 만들었다.

하지만 아쉬운 점은 Class 화를 하지 않아서 좀 불편한 면이 있다.

아래 Class 는 나의 사용 환경에 맞게 변경하거나 신규 기능을 추가하여 사용하고 있다.

본인만의 함수를 만들면 코딩이 간단해지고 직관적으로 이해할 수 있다.


MySQL 접속 환경이 MySQL 인가? MySQLi 인가? 에 따라 함수를 선택해서 사용하면 된다.


함수 사용법

===== dbconnect.php ======

include_once $_SERVER['DOCUMENT_ROOT'].'/db.info.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
$conn=new MySQLDbClass();
$DB_CONNECT = $conn->isConnectDb($DB);


===== db.info.php ===== 파일에는 접속 정보가 들어가 있다.

<?php
$DB['host'] = "localhost";
$DB['name'] = "DB명";
$DB['user'] = "DB접속ID";
$DB['pass'] = "DB패스워드";
$DB['port'] = "3306";
$DB['type'] = "MyISAM";
?>


===== dbClass.php ======

<?php
class MySQLDbClass {

    function isConnectDb($db) {
        $conn = mysql_connect($db['host'].':'.$db['port'],$db['user'],$db['pass']);

        mysql_query("SET CHARSET utf8");

        mysql_query("SET NAMES 'utf8' COLLATE 'utf8_general_ci'");

        if(!$conn){
            die('Not connected :' . mysql_error());
            exit;
        }
        $selc = mysql_select_db($db['name'],$conn); // 접근한 계정으로 사용할 수 있는 DB 선택
        // 연결 식별자($conn) 는 생략 가능하며, 생략시 가장 최근에 설정한 연결 식별자가 사용된다.
        return $selc ? $conn : false;
    }

    //DB-UID데이터
    function getUidData($table,$uid){
        return $this->getDbData($table,'uid='.(int)$uid,'*');
    }

    // DB Query Cutom 함수
    function getDbData($table,$where,$column){
        global $DB_CONNECT;
        $result = mysql_query('select '.$column.' from '.$table.($where?' where '.$this->getSqlFilter($where):''));
        $row = mysql_fetch_array($result);
        return $row;
    }

    // DB Query result 함수
    function getDbresult($table,$where,$column){
        global $DB_CONNECT;
        $result = mysql_query('select '.$column.' from '.$table.($where?' where '.$this->getSqlFilter($where):''));
        return $result;
    }

    //DB데이터 필드 개수
    function getDbColums($table,$where,$column){
        global $DB_CONNECT;
        $result = mysql_query('select '.$column.' from '.$table.($where?' where '.$this->getSqlFilter($where):''));
        return mysql_num_fields($result);
    }

    //DB데이터 레코드 총 개수
    function getDbRows($table,$where){
        global $DB_CONNECT;
        $sql = 'select count(*) from '.$table.($where?' where '.$this->getSqlFilter($where):'');
        //echo $sql;
        $rows = mysql_fetch_array(mysql_query($sql));
        return $rows[0] ? $rows[0] : 0;
    }

    //DB데이터 ARRAY -> 테이블에 출력할 데이터 배열
    // order by : 정렬 순서, limit : 화면에 출력할 개수, curPage : 현재 페이지
    function getDbArray($table,$where,$flddata,$orderby,$limit,$curPage){
        global $DB_CONNECT;
        $curPage = $curPage ? $curPage : 1; // 현재 페이지가 없으면 1로 설정
        $sql = 'select '.$flddata.' from '.$table.($where?' where '.$this->getSqlFilter($where):'').($orderby?' order by '.$orderby:'').($limit?' limit '.(($curPage-1)*$limit).', '.$limit:'');
        //echo $sql;
        $result = mysql_query($sql);
        return $result;
    }

    //DB select
    function getDbSelect($table,$where,$column){
        global $DB_CONNECT;
        $row = mysql_query('select '.$column.' from '.$table.($where?' where '.$this->getSqlFilter($where):''),$DB_CONNECT);
        return $row;
    }

    //DB삽입
    function getDbInsert($table,$key,$val){
        global $DB_CONNECT;
        mysql_query("insert into ".$table." (".$key.")values(".$val.")");
    }

    //DB업데이트
    function getDbUpdate($table,$set,$where){
        global $DB_CONNECT;
        mysql_query('set names utf8');
        mysql_query('set sql_mode=\'\'');
        mysql_query("update ".$table." set ".$set.($where?' where '.$this->getSqlFilter($where):''));
    }

    //DB삭제
    function getDbDelete($table,$where){
        global $DB_CONNECT;
        mysql_query("delete from ".$table.($where?' where '.$this->getSqlFilter($where):''),$DB_CONNECT);
    }

    //SQL필터링
    function getSqlFilter($sql){
        return $sql;
    }

}//end dbClass

class MySQLiDbClass {
    function isConnectDb($db)
    {
        $conn = mysqli_connect($db['host'],$db['user'],$db['pass'],$db['name'],$db['port']);
        mysqli_set_charset($conn, "utf8");  // DB설정이 잘못되어 euc-kr 로 되어 있으면 문제가 됨
        if (mysqli_connect_errno()) {
           printf("Connect failed: %s\n", mysqli_connect_error());
           exit();
        } else {
          return $conn;   
        }
    } // */

    //DB-UID데이터
    function getUidData($table,$uid)
    {
        return $this->getDbData($table,'uid='.(int)$uid,'*');
    }

    // DB Query Cutom 함수
    function getDbData($table,$where,$column) {
        global $DB_CONNECT;
        $result = mysqli_query('select '.$column.' from '.$table.($where?' where '.$this->getSqlFilter($where):''));
        $row = mysqli_fetch_array($result);
        return $row;
    }

    // DB Query result 함수
    function getDbresult($table,$where,$column) {
        global $DB_CONNECT;
        $result = mysqli_query('select '.$column.' from '.$table.($where?' where '.$this->getSqlFilter($where):''));
        return $result;
    }

    //DB데이터 ARRAY -> 테이블에 출력할 데이터 배열
    function getDbArray($table,$where,$flddata,$orderby,$limit,$curPage){
        global $DB_CONNECT;
        $sql = 'select '.$flddata.' from '.$table.($where?' where '.$this->getSqlFilter($where):'').($orderby?' order by '.$orderby:'').($limit?' limit '.(($curPage-1)*$limit).', '.$limit:'');
        $result = mysqli_query($sql);
        return $result;
    }

    //DB데이터 레코드 총 개수
    function getDbRows($table,$where){
        global $DB_CONNECT;
        $sql = 'select count(*) from '.$table.($where?' where '.$this->getSqlFilter($where):'');
        $rows = mysqli_fetch_array(mysqli_query($sql));
        return $rows[0] ? $rows[0] : 0;
    }

    //DB삽입
    function getDbInsert($table,$key,$val){
        global $DB_CONNECT;
        mysqli_query("insert into ".$table." (".$key.")values(".$val.")");
    }

    //DB업데이트
    function getDbUpdate($table,$set,$where){
        global $DB_CONNECT;
        mysqli_query('set names utf8');
        mysqli_query('set sql_mode=\'\'');
        mysqli_query("update ".$table." set ".$set.($where?' where '.$this->getSqlFilter($where):''));
    }

    //DB삭제
    function getDbDelete($table,$where)    {
        global $DB_CONNECT;
        mysqli_query("delete from ".$table.($where?' where '.$this->getSqlFilter($where):''),$DB_CONNECT);
    }

    //SQL필터링
    function getSqlFilter($sql)
    {
        return $sql;
    }

}//end dbClass

?>

728x90
블로그 이미지

Link2Me

,

ajax 에 대한 기본 개념이 잘 설명된 곳은 https://www.w3schools.com/jquery/jquery_ajax_intro.asp 다.

ajax 의 강력한 특징은 페이지 전체를 refresh 하지 않고서도 수행되는 비동기성이다. 이러한 비동기성을 통해 사용자의 Event가 있으면 전체 페이지가 아닌 일부분만을 업데이트 할 수 있게 해준다.


jQuery ajax 의 다른 형태로 .get 또는 .post 처리가 가능하다.

형태가 심플하여 더 편할 수 있다. 아래 코드는 100% 동작하는 걸 확인하고 적어둔다.

대부분 자료들이 대략적인 컨셉만 적혀있고 참고로 사용할만한 샘플이 없는 거 같아서 적었다.

나와 같은 초보자들은 제대로 동작하는 샘플이 있어야만 그 다음에 응용 또는 활용이 가능하다.


$.get()함수, $.post() 함수는 url, url 파라미터, 요청의 성공시 응답을 받기 위한 콜백함수가 있다.

$.post(url, {userID:input_value}, function(data) {

     // 통신이 성공했을 때 실행하는 함수

}, 'json');


url 파라미터는 key 와 value 쌍으로 구성된다. 파라미터가 여러개이면 콤마로 구분한다.


===== idCheck.php ====

<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<title>ID Join Check</title>
<!-- 모바일 웹 페이지 설정 -->
<link rel="shortcut icon" href="img/icon.png" />
<link rel="apple-touch-icon" href="img/icon.png" />
<!-- 모바일 웹 페이지 설정 끝 -->

<link rel="stylesheet" type="text/css" href="css/common.css"/>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="js/idCheck.js"></script>
</head>
<body>
    <h1 class="title">아이디 중복검사</h1>
    <div class="exec">
        <form>
            <input type="text" name="userID" />
            <input type="button" id="checkid" value="중복검사" />
        </form>
    </div>
    <div class="console"></div>
</body>
</html>


===== idCheck.js =====

$(function(){
    $("#checkid").click(function(e) {

        e.preventDefault(); // a 링크, form submit 실행 방지

        var input_value = $("input[name='userID']").val();
       
        // 입력 여부 검사
        if(!input_value) {
            alert("아이디를 입력하세요");
            $("input[name='userID']").focus();
            return false;
        }

        var url = 'idCheck_ok.php';
        $.post(url, {userID:input_value}, function(msg) {
            if (msg.result==1) { // idCheck_ok.php 의 결과값
                $(".console").html("<span style='color:blue'>사용할 수 있는 아이디 입니다.</span>");

                // alert('사용할 수 있는 아이디 입니다.'); 로 대신해도 된다.

            } else {
                $(".console").html("<span style='color:red'>사용할 수 없는 아이디 입니다.</span>");

                // alert('사용할 수 없는 아이디 입니다.'); 로 대신해도 된다.

                // 이 경우에는 $("input[name='userID']").val(''); 로 입력값을 초기화해도 좋다.

            }
        },'json');
       
    });
});



https://link2me.tistory.com/954 참조하면 javascript 로 Form 제어하는 개념을 이해할 수 있다.

위의 예제에는 form method, action 을 생략해서 원하는 결과를 얻지 못할 수 있다.

form method를 생략하면 GET방식으로 동작된다.

form action 을 추가하고 동작할 경우에는 반드시 e.preventDefault(); // a 링크, form submit 실행 방지

를 추가해줘야 제대로 원하는 결과를 얻을 수 있다.


===== idCheck_ok.php ====

# PHP 기본 개념 이해는 http://link2me.tistory.com/1110 게시글을 참조하시라.

# ajax 를 이용하면 파일 A --> 파일 B로 이동하지 않고 결과를 얻을  수 있다.

<?php
session_start();
if(isset($_POST['userID']) && !empty($_POST['userID'])) {
    $userID = trim($_POST['userID']);

    require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; // db접속 성공
    require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/loginClass.php';

    $c=new LoginClass();
    $rs = $c->UserIDJoinCheck($userID);
    if($rs == '0') {
        echo '{"result":"1"}';
    } else {
        echo '{"result":"0"}';
    }
}
?>

===== loginClass.php ====

<?php
class LoginClass {
    function UserIDJoinCheck($userID) {
        if(!isset($userID) || empty($userID)) {
            return '-1';
        } else {
            global $db;           
            $userID = preg_replace("/[\s\t]+/","", $userID); // 공백이나 탭 제거(사용자 실수 방지)

            $sql = "select id, count(id) ";
            $sql.= "from rb_s_mbrid where id= '".$userID."' ";
            if($result = mysqli_query($db,$sql)) { //성공
                $row = mysqli_fetch_row($result);
                if($row[1] == '0') return 0;
                return $row[1];
            } else {
                return '-1';
            }
        }
    }

}//end class LoginClass

?>


===== 테이블 구조 =====

CREATE TABLE IF NOT EXISTS `rb_s_mbrid` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `site` int(11) NOT NULL DEFAULT '0',
  `id` varchar(50) NOT NULL DEFAULT '',
  `pw` varchar(50) NOT NULL DEFAULT '',
  `code` int(6) NOT NULL DEFAULT '0',
  PRIMARY KEY (`uid`),
  KEY `site` (`site`),
  KEY `id` (`id`),
  KEY `code` (`code`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

도움되셨다면 공감 또는 ... 눌러주세요.

728x90
블로그 이미지

Link2Me

,
PHP 로 파싱하는 것은 아직 안해봤다. PHP 로 파싱하는 걸 알면 여러모로 편리할 거 같기는 하다.

다른 Web 사이트에 있는 정보를 가져와서 재가공 해야 하는 경우에 Snoopy.class.php 를 활용하면 된다.


Snoopy 클래스 다운로드 http://sourceforge.net/projects/snoopy/files/latest/download


네이버지식인 답변에 올라온 것을 적어둔다.

답변자 출처 : http://dolgo.net/php/questions/85

<?php
include_once 'snoopy/Snoopy.class.php';
$snoopy = new Snoopy;
$getUrl = "http://www.645lotto.net/lotto645Confirm.do?method=byWin&drwNo=710";
$snoopy->fetch($getUrl);
$pattern='/img src="\/img\/common\/ball_(.*?).png/';
preg_match_all($pattern,$snoopy->results,$out); 
for($i=0;$i<=6;$i++){
    echo $out[1][$i]."\n";
}
?>


분석

- $snoopy = new Snoopy; // Class화된 PHP는 객체 생성을 해야 함

- 확장자를 do를 사용하는 것은 PHP 인지 JSP 인지 식별할 수 없게 하기 위함이다.

- 로또번호 회차 표시부분을 수정하면 매번 다르게 보일 것이다.

- fetch($getUrl) : 입력받은 주소의 html소스를 텍스트 형식으로 $results에 저장

- fetchlinks($URI) : fetch와 비슷하지만 링크만을 배열의 형태로 $results에 저장

- fetchtext($URI) : fetch와 비슷하지만 스크립트를 제외한 텍스트만 $results에 저장

- fetchform($URI) : fetch와 비슷하지만 폼 부분을 html형식으로 $results에 저장

- submit($URI, $formvars="", $formfiles="") : 폼에 여러 변수를 붙여서 전송 가능

- setcookies() : 종종 쿠키정보를 유지해야하는 경우가 있을 때 사용

- preg_match 정규식을 사용해서 이제 본문 필요 요소만을 추출



728x90

'Web 프로그램 > JSON, 파싱 다루기' 카테고리의 다른 글

Parse JSON with PHP (JSON 파싱)  (2) 2017.11.27
PHP Array 활용 JSON  (0) 2017.05.11
[PHP] MySQL Data to JSON using PHP  (0) 2016.12.22
XML 데이터 생성 처리  (0) 2016.06.06
PHP 와 XML 연동처리  (0) 2016.06.04
블로그 이미지

Link2Me

,

// DB Query Cutom 함수
function getDbData($table,$where,$data,$orderby){
    global $db;
    $result = mysql_query('select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):'').($orderby?' order by '.getSqlFilter($orderby):''));
    $row = mysql_fetch_array($result);
    return $row;
}

//SQL필터링
function getSqlFilter($sql){
    return $sql;
}


함수를 만들어서 사용할 경우 제대로 잘 만들어졌는지 테스트 하는 과정은 아래과정으로 진행했다.

sql 쿼리문을 화면상에 나오게 하여 제대로 나왔는지 확인했다.


<?php
$table ='MEMBER';
$part1CD='04';
$part2CD='23';
$part3CD='00';
$partNM = '기타';
$where ="part1CD='".$part1CD."' and part2CD='".$part2CD."' and part4CD='00' and partNM='".$partNM."'";
$data ='*';
$orderby = 'idx DESC';
//$orderby = '';

$sql = 'select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):'').($orderby?' order by '.getSqlFilter($orderby):'');
echo $sql;

function getSqlFilter($sql)
{
    return $sql;
    // preg_replace("/찾을 문자열/" , "변경할 문자열" , "해당 문자열");
    // /찾을 문자열/ 에서 / 는 정규식의 시작과 끝을 알린다.
    //return preg_replace("( union| update| insert| delete| drop|\/\*|\*\/|\\\|\;)",'',$sql);
}

?>

728x90
블로그 이미지

Link2Me

,

파일을 업로드하는 코딩시 고려할 사항이다.


파일을 업로드시에 공격이 성공하면 바로 서버가 해킹되는 것이기 때문에 가장 리스크가 큰 취약점이다.

보안(Security)을 고려하고 실행파일이 업로드되지 않도록 해야 한다.

먼저, 파일 업로드 기능이 있는 페이지를 전부 조사해서 WebShell 같은 악의적인 파일이 업로드될 수 있는지 체크해야 한다.


1. 파일 업로드시 확장자 검사 루틴

    - 기본적으로는 Apache 환경설정에서 mine type 필터링을 설정한다.

      Apache 환경설정 http://link2me.tistory.com/426  http://link2me.tistory.com/991 참조

    <IfModule mime_module>
        TypesConfig conf/mime.types
        AddType application/x-compress .Z
        AddType application/x-gzip .gz .tgz
        AddType application/x-httpd-php .php .html
        AddType application/x-httpd-php-source .phps
    </IfModule>


   - 하지만 공격자가 Proxy-Server 등을 통해 우회할 수 있으므로 확장자 필터링을 적용한다.

     업로드가 허용된 확장자만 업로드가 가능하도록 서버 필터링을 하여야 한다.

 

2. 파일명은 치환(난수화)해서 저장한다.
    그리고 파일 접근권한을 읽기 전용모드로 등록한다. (실행권한 부여 금지)


3. 등록시 변경 파일명을 DB에 저장한다.

    - 게시판에 첨부되는 파일명인 경우, 변경 파일명을 DB 테이블에 기록하여 찾을 수 있도록 한다.


4. 가능하면 파일 업로드 장소를 물리적으로 분리한다.

    물리적으로 분리하지 않은 경우라면 해당 디렉토리가 어디인지 알수 없게 다른 곳으로 지정한다.


파일 업로드시 제한 용량은 php.ini 파일에 설정되어 있다.

업로드 용량을 많이 설정하려면 php.ini 파일을 수정하고 Apache 를 restart 해야 한다.

; PHP 가 받아들이는 POST data 최대 크기
; default 8M 로 되어 있음, upload_max_filesize 보다 크게 설정해야 함
post_max_size = 20M
memory_limit = 128M
upload_max_filesize = 19M


// 테이블 구조 예시

CREATE TABLE IF NOT EXISTS file_upload (
  uid int(11) NOT NULL AUTO_INCREMENT,
  folder varchar(10) NOT NULL DEFAULT '',
  name varchar(250) NOT NULL DEFAULT '',
  size int(11) NOT NULL DEFAULT '0',
  d_regis varchar(14) NOT NULL DEFAULT '',
  PRIMARY KEY (uid),
  KEY d_regis (d_regis)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;


//파일을 전송하는 PHP 소스 부분

파일명을 excel 로 사용했으면 받는 쪽에서도 excel 로 사용해야 한다.

보통은 userfile 이라고 많이 쓴다.

<form enctype="multipart/form-data" action="fileupload.php" method="POST">
 <input 
type="file" name="excel"  />

 <input type="submit" value="upload" />
</form>



// 파일을 전송받은 PHP 소스 부분

여러개의 확장자를 검사하려면 strstr('[csv]',$fileExt) 부분을 수정하면 된다.

strstr('[csv,php,html,htm,inc,do]',$fileExt) 와 같이 확장자 여러개를 나열해준다.


<?php
    // Edit upload location here
    $tmpname    = $_FILES['excel']['tmp_name'];
    $realname    = $_FILES['excel']['name'];
    $fileExt    = getExt($realname);  // 확장자 필터링을 위한 확장자 추출
    $destination_path='uploads/';
    $rndname = hash('sha256', $realname).date("Ymd").'.'.$fileExt;  // 파일명 hash 처리
    $readFile = $destination_path . $rndname;

    if (is_uploaded_file($tmpname)) {
        if (!strstr('[csv]',$fileExt)) {  // 확장자 필터링 검사
            echo '<script type="text/javascript">alert("csv 파일만 등록할 수 있습니다.");</script>';
            exit;
        }
        move_uploaded_file($tmpname,$readFile);
        @chmod($readFile,0404);  // 파일 권한을 읽기모드로 설정

    }

    function getExt($filename){
        $ext = substr(strrchr($filename,"."),1); // 뒤에서부터 콤마 위치로부터 가져오기
        $ext = strtolower($ext); // 소문자로 강제치환
        return $ext;
    }

    ?>



아래 코드는 업로드시 파일명을 치환하는 연습 코드이다.


<?php
//$realname = strtolower($_FILES['excel']['name']);
$realname = 'shell.asp;.jpg';
$fileExt = getExt($realname);
//$tmpname = md5($realname).date("Ymd").'.'.$fileExt;
$tmpname = hash('sha256', $realname).date("Ymd").'.'.$fileExt;

echo $tmpname;
echo '<br />';
echo strlen($tmpname);

function getExt($filename){
    $ext = substr(strrchr($filename,"."),1); // 뒤에서부터 콤마 위치로부터 가져오기
    $ext = strtolower($ext); // 소문자로 강제치환
    return $ext;
}

?>


파일을 2개 업로드하는 걸 고려한다면

<form enctype="multipart/form-data" action="fileupload.php" method="POST">

이미지 파일1 <input type="file" name="imagefile[]">

이미지 파일2 <input type="file" name="imagefile[]">

<input type="submit" value="upload" />

</form>


fileupload.php 에서 확인해 볼 사항

echo '<pre>', print_r($_FILES) ,"</pre>";

$_FILES['imagefile']['name'][0];

$_FILES['imagefile']['name'][1];

$_FILES['imagefile']['type'][0];

$_FILES['imagefile']['type'][1];

$_FILES['imagefile']['tmp_name'][0];

$_FILES['imagefile']['tmp_name'][1];

$_FILES['imagefile']['size'][0];

$_FILES['imagefile']['size'][1];

$_FILES['imagefile']['error'][0];

$_FILES['imagefile']['error'][1];


참조하면 도움되는 게시글

http://blog.habonyphp.com/entry/php-POST-%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C#.V5RntaKzHpU


jQuery PHP 파일 업로드 게시글 : http://link2me.tistory.com/1142


Ajax PHP 파일 업로드 게시글 : http://link2me.tistory.com/1143

728x90
블로그 이미지

Link2Me

,

서버가 CentOS7 환경이라면 https://link2me.tistory.com/1842 를 참고해야 한다.


웹파일 형식으로 내보내기를 하면 속도가 짱 빠르기 때문에 사용하는데 문제가 없다.

<?php
if(!isset($_SESSION)) {
    session_start();
}

$file_name = "xxx_code.xls";
header( "Content-type: application/vnd.ms-excel; charset=utf-8");
header( "Cache-Control: must-revalidate, post-check=0,pre-check=0" );
header( "Content-Disposition: attachment; filename=$file_name" );
header( "Content-Description: PHP4 Generated Data" );


error_reporting(E_ALL ^ E_NOTICE);

include_once 'db.info.php';
include_once 'function/db.mysql.func.php';
$DB_CONNECT = isConnectDb($DB);


?>


윈도우10 환경하에서 인식이 제대로 안되는 현상이 생겨서 이번 기회에 엑셀 파일로 직접 저장하는 법을 찾아봤다.

엑셀로 저장하면 일단 속도가 많이 느리다.


https://github.com/PHPOffice/PHPExcel 에서 파일을 다운로드한다.

다운로드 한 파일을 압축을 풀어서 서버에 업로드한다.


아래 코드처럼 작성하면 된다.


<?php
if(!isset($_SESSION)) {
    session_start();
}
if(!empty($_SESSION['userID'])){
    echo "<script>window.top.location.replace('/index.php');</script>";
    exit;
}

$fname="xxx_code";  // 저장할 파일명
// 파일의 저장형식이 utf-8일 경우 한글파일 이름은 깨지므로 euc-kr로 변환해준다.
//$fname = iconv("UTF-8", "EUC-KR", "한글이름");

require_once "dbconnect.php";
require_once 'phpclass/PHPExcel.php';

$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0); //set first sheet as active

$objSheet = $objPHPExcel->getActiveSheet();
$objSheet->setTitle('코드');
$objSheet->getCell('A1')->setValue('코드');
$objSheet->getDefaultStyle('A1')->getFont()->setName('맑은 고딕');
$objSheet->mergeCells('A1:M1'); // 셀 병합
$objSheet->getStyle('A1')->getFont()->setSize(16); // 셀의 textsize

$objPHPExcel->getDefaultStyle()->getFont()->setSize(12); // 폰트 사이즈
$objSheet->SetCellValue('A2', "NO");
$objSheet->mergeCells('A2:A3'); // 셀 병합
$objSheet->SetCellValue('B2', "부서");
$objSheet->mergeCells('B2:E2');
$objSheet->SetCellValue('F2', "순서");
$objSheet->mergeCells('F2:I2');
$objSheet->SetCellValue('J2', "코드");
$objSheet->mergeCells('J2:M2');

$objSheet->SetCellValue('B3', "부서1");
$objSheet->SetCellValue('C3', "부서2");
$objSheet->SetCellValue('D3', "부서3");
$objSheet->SetCellValue('E3', "부서4");

$objSheet->SetCellValue('F3', "계위1");
$objSheet->SetCellValue('G3', "계위2");
$objSheet->SetCellValue('H3', "계위3");
$objSheet->SetCellValue('I3', "계위4");

$objSheet->SetCellValue('J3', "계위1");
$objSheet->SetCellValue('K3', "계위2");
$objSheet->SetCellValue('L3', "계위3");
$objSheet->SetCellValue('M3', "계위4");

cellColor('A2:M3', 'F28A8C'); // 헤더 배경색 지정

$i=4; // 값을 기록할 셀의 시작위치
$rowCount = 1; // 넘버링

$sql="select * from tablename where 조건";
$result=mysql_query($sql);
while($row=mysql_fetch_row($result)){


    $objSheet->SetCellValue('A'.$i, $rowCount);
    $objSheet->SetCellValue('B'.$i, $row[0]);
    $objSheet->SetCellValue('C'.$i, $row[1]);
    $objSheet->SetCellValue('D'.$i, $row[2]);
    $objSheet->SetCellValue('E'.$i, $row[3]);

    $objSheet->SetCellValue('F'.$i, $row[4]);
    $objSheet->SetCellValue('G'.$i, $row[5]);
    $objSheet->SetCellValue('H'.$i, $row[6]);
    $objSheet->SetCellValue('I'.$i, $row[7]);

    $objSheet->SetCellValue('J'.$i, $row[8]);
    $objSheet->SetCellValue('K'.$i, $row[9]);
    $objSheet->SetCellValue('L'.$i, $row[10]);
    $objSheet->SetCellValue('M'.$i, $row[11]);

    $i++;
    $rowCount++;
}

// 표 그리기
$i--;
$objSheet->getStyle('A2:M'.$i)->getBorders()->getAllBorders()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);

// 헤더 칼럼 가운데 정렬
$objSheet->getStyle('A2:M'.$i)->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

// 셀 높이
$objSheet->getRowDimension(1)->setRowHeight(20);

// 칼럼 사이즈 자동 조정
$objSheet->getColumnDimension('A')->setAutoSize(true);
$objSheet->getColumnDimension('B')->setWidth(18);  // 칼럼 크기 직접 지정
$objSheet->getColumnDimension('C')->setWidth(18);
$objSheet->getColumnDimension('D')->setWidth(18);
$objSheet->getColumnDimension('E')->setWidth(18);

// 파일 PC로 다운로드
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename='.$fname.'.xlsx');
header('Cache-Control: max-age=0');

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, "Excel2007");
$objWriter->save('php://output');
exit;

function SaveViaTempFile($objWriter){
    $filePath = '/tmp/' . rand(0, getrandmax()) . rand(0, getrandmax()) . ".tmp";
    $objWriter->save($filePath);
    readfile($filePath);
    unlink($filePath);
}

// 엑셀의 셀 배경색 지정
function cellColor($cells,$color){
    global $objSheet;

    $objSheet->getStyle($cells)->getFill()->applyFromArray(array(
        'type' => PHPExcel_Style_Fill::FILL_SOLID,
        'startcolor' => array(
             'rgb' => $color
        )
    ));
}

?>

728x90
블로그 이미지

Link2Me

,

PHP 를 이용하여 MySQL 칼럼명을 가져오는 코드를 필요했다.

테이블을 INNER JOIN 하면서 select * from tableA a, tableB b where a.uid=b.uid 로 하면 tableA 와 tableB의 모든 칼럼을 가져오게 된다.


가져오고 싶은 것은 tableA의 칼럼만 가져오고 싶어서 함수로 구현했다.


<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; //db접속

echo getColumns('member_table'); // table name

function getColumns($table){

    global $DB_CONNECT;
    $fields = array();
    $res=mysql_query("SHOW COLUMNS FROM ".$table."");
    while ($x = mysql_fetch_assoc($res)){
      array_push($fields,$x['Field']);
    }

    for($i = 0; $i < count($fields); $i++){
        $columns = join($fields,",");
    }
    return $columns;
}

?>


728x90
블로그 이미지

Link2Me

,

<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(function(){
    $("#sel2").click(function(){
        cw=screen.availWidth;     //화면 넓이
        ch=screen.availHeight;    //화면 높이

        sw=cw/2;    //띄울 창의 넓이
        sh=ch/2;    //띄울 창의 높이

        ml=(cw-sw)/2; //가운데 띄우기위한 창의 x위치
        mt=(ch-sh)/2; //가운데 띄우기위한 창의 y위치

        var url = $("#sel").val();
        if(url != '0'){
            window.open(url, 'tst','width='+sw+',height='+sh+',top='+mt+',left='+ml+',resizable=no,scrollbars=yes');
        }

    });
});
</script>
<body>
<select id="sel">
  <option value="0" >선택 사이트로 이동</option>
  <option value="http://link2me.tistory.com">My Blog</option>
  <option value="http://www.naver.com">네이버</option>
  <option value="http://www.daum.net">다음</option>
 </select><a href="#" id="sel2" >이동</a>

</body>
</html>

728x90
블로그 이미지

Link2Me

,

<input type="button" id="orderBtn" name="Test" value = "순서변경"></button>


MouseOver 시 손가락 모양 표시

css로 손가락 모양을 만든다.


    $('#orderBtn').css("cursor","pointer").click(function() {
        $.ajax ({
            type:"POST",
            url:"./order_process.php",
            data:ordered_items,
            success:function(data) {
                alert ("서열순서를 DB에 반영했습니다.");
            }
        });   
    });

728x90

'Web 프로그램 > js, jQuery' 카테고리의 다른 글

jQuery 모달(dialog) 코드 이해하기  (2) 2016.10.11
jQuey 새창 띄우기  (0) 2016.07.11
jQuery 모달(modal) 윈도우  (0) 2016.05.01
JSON 기초  (0) 2016.04.24
부모창 새로 고침  (1) 2016.04.10
블로그 이미지

Link2Me

,

테이블 게시글 순서를 변경 저장해야 할 경우가 있다.

그래서 jQuery tableDnD 를 이용해서 테스트한 것을 적어둔다.


마우스로 Drag 하여 놓기를 하고  순서변경만 누르면 DB에 반영된다.




파일은 https://github.com/isocra/TableDnD 에서 다운로드 받아 jquery.tablednd.js 만 include 한다.


순서를 변경하는 것은 직급 서열 순서를 변경하는 경우에 처리할 것이므로, 화면에 표시할 게시글수를 2페이지로 분리해서 나오도록 하면 안된다.

그래서 limit 에 조건을 만족하는 개수만큼 표시되도록 처리했다.


<?php
session_start();
// 세션 검사 처리는 생략
// DB 연결
include_once $_SERVER['DOCUMENT_ROOT'].'/db.info.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
$c=new MySQLDbClass();
$DB_CONNECT = $c->isConnectDb($DB);

$where =""; // where 조건문
$limit = $NUM = $c->getDbRows('BOOKS',''); // 조건에 맞는 게시글 개수
$flddata ="uid, title, price, category, orderNO";
$orderby = "orderNO";
$curPage = 1;
$result = $c->getDbArray('BOOKS',$where,$flddata,$orderby,$limit,$curPage);

?>

<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="js/jquery.tablednd.js"></script>
<style>
body {font-family: "맑은 고딕";}
table,td,th {border: 1px solid #000;border-collapse:collapse;padding:5px;}
/*사용자 정의 스타일 */
.dragRow {background-color: #fee;}

td.dragHandle {}

td.showDragHandle {
    background-image: url(images/updown2.gif);
    background-repeat: no-repeat;
    background-position: center left;
    cursor: move;
}

table td {padding:5px;}
</style>

<script>
$(function() {
    var ordered_items;
    $('#table_1').tableDnD({
        onDragClass: "dragRow",
        onDrop: function(table, row) {
        ordered_items = $.tableDnD.serialize('id');
        }
    });

    $('#btn_order').css("cursor","pointer").click(function() {
        $.ajax ({
            type:"POST",
            url:"./order_process.php",
            data:ordered_items,
            success:function(data) {
                alert ("서열순서를 DB에 반영했습니다.");
            }
        });   
    });


    // class td1 중에서 짝수번째 요소만 선택해서 배경색을 지정색으로 표시
    $(".tr1:odd").css("background-color","#F4F9FF");

}); // ready

</script>
<body>
<div class="container">
    <div id="article">
        총 : <?php echo number_format($NUM)?> 개
    </div>

    <section id="content">
        <table id="table_1" border="1" style="width:800px;">
        <tr class="nodrop nodrag"><!-- Drag & Drop 제외 -->
            <th>uid</th>
            <th>타이틀</th>
            <th>가격</th>
            <th>구분</th>
            <th style="width:50px;">순번</th>
        </tr>
        <?php
        while($row = mysql_fetch_array($result)){
            echo '<tr id="'.$row[0].'" class="tr1">';
            for($i=0;$i < count(explode(",",$flddata)); $i++){
                echo '<td>'.$row[$i].'</td>';
            }
            echo '</tr>';
        }
        ?>
        </table>
        <input type="button" id="btn_order" name="Test" value = "순서변경"></button>
    </section><!-- content -->
</div><!-- container -->
</body>
</html>


===== order_process.php =====

<?php
if(!isset($_POST['table_1'])) {
    echo 'error';
    exit;
}

$table_1 = $_POST['table_1'];
foreach ($table_1 as $key=>$value) {
    // 정렬순서 변경내역 DB에 반영
    require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; // db접속
    $query = 'UPDATE BOOKS SET orderNO = '.($key+1).' WHERE uid = '.$value.' LIMIT 1';
    mysql_query($query) or die (mysql_error());
}

?>



728x90
블로그 이미지

Link2Me

,

테이블 게시물 순서 바꾸기를 연습해봤다.

테이블 순서를 변경해주는 jQuery 소스는 https://github.com/isocra/TableDnD 에서 받을 수 있다.

jquery.tablednd.js


첨부로 올린 이 파일을 받아도 된다.

이것은 테이블에서 마우스로 위아래 게시물 순서를 변경할 수 있다는 것만 연습해볼 수 있다.

DB와 연동하여 실제 게시물 순서를 변경하는 것 까지는 안된다.

하지만 거의 DB에서 가져온 것과 같은 결과를 얻어내는 방법까지 설명을 추가했다.


<!DOCTYPE html>
<head>
<meta charset=UTF-8" />
<meta name="robots" content="noindex,nofollow"/> <!-- 검색엔진에서 검색 제외 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" /> <!--브라우저 호환성 설정 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="js/jquery.tablednd.js"></script>
<style>
body {font-family: "맑은 고딕";}
table,td,th {border: 1px solid #000;border-collapse:collapse;padding:5px;}
/*사용자 정의 스타일 */
.dragRow {background-color: #eee;}

td.dragHandle {}

td.showDragHandle {background-image: url(images/updown2.gif);
    background-repeat: no-repeat;background-position: center left;
    cursor: move;
}

table td {padding:5px;}
</style>

<script>
$(function() {
    var ordered_items;
    onDragClass: "drag",
    $('#table_1').tableDnD({
        onDrop: function(table, row) {
        ordered_items = $.tableDnD.serialize('id');
        }
    });

    $('#btn_order').click(function() {
        $('#result').load("test.php?" + ordered_items);
    });

});
</script>
</script>


<div id="result">테이블 순서변경 결과 메시지 보여주는 곳</div>
<br>
<table id="table_1" border="1" style="width: 500px;">
    <tr id="1"><td>1</td><td>첫번째</td></tr>
    <tr id="2"><td>2</td><td>두번째</td></tr>
    <tr id="3"><td>3</td><td>세번째</td></tr>
    <tr id="4"><td>4</td><td>네번째</td></tr>
    <tr id="5"><td>5</td><td>다섯번째</td></tr>
</table>
<input type="button" id="btn_order" name="Test" value = "순서변경"></button>


</body>
</html>


===== test.php =====

<?php
$table_1 = $_GET['table_1'];
echo '저장순서 : ';
foreach ($table_1 as $key=>$value) {
    echo '순번 '. ($key+1) . ' 번의 DB idx = '. $value . ', ';
    // DB에 결과를 반영하고자 하는 쿼리문을 적어준다
    // $query = 'UPDATE table SET orderNO = '.($key+1).' WHERE idx = '.$value.' LIMIT 1';
    // mysql_query($query) or die (mysql_error());
}

?>


DB에서 읽어온 파일을 테이블로 구성한다면 <tr id='row['idx']'> 에 값이 저장되도록 한다.

테이블의 순서를 변경하면 자동으로 DB에 저장된 순서로 orderNO 에 순서의 값이 저장된다.


게시물을 읽어서 테이블에 보여주는 개수를 잘 처리하는 것이 중요 포인트가 될 수도 있다.

가령 뽑아내야 할 게시글의 수가 18개 였다고 가정해보자.

그러면 화면에서는 18개가 모두 나오도록 처리하는게 중요하다.

화면에 출력해야 할 Query 문의 개수(count)를 구한 다음에 그 개수만큼 출력하려면 LIMIT $count 만큼 나오도록 쿼리문을 만들어야 한다.

728x90
블로그 이미지

Link2Me

,

SQL 인젝션 공격을 방지하기 위한 로그인 함수 사용예이다.

공격코드로 사용하는 특수문자를 전부 공백으로 대체시켜 버리도록 했다.


function UserAuthCheck($userID,$passwd) {
    if(!isset($userID) || !isset($passwd) || empty($userID) || empty($passwd)) {
        return 0;
    } else {
        global $DB_CONNECT;           
        $userID = preg_replace("/[\s\t\'\;\"\=\-\-]+/","", $userID); // 공백이나 탭 제거(사용자 실수 방지)
        $passwd = preg_replace("/[\s\t\'\;\"\=\-\-]+/","", $passwd); // 공백이나 탭 제거, 특수문자 제거(",',;,=,--)
        // SQL injection 검사
        $userID = htmlentities($userID); // <script>documnet.cookie();</script> 공격 방지, 한글인식 불가
        $passwd = htmlentities($passwd); // < 를 \< 로 바꿔준다.
        //$userID = str_replace(array("'",""","'",'"'), array("&#39;","&quot;","&#39;","&quot;"), $userID);
        if(preg_match('/(and|null|where|limit)/i', $userID)) { $this->popup('비정상적 접근입니다');} // i는 대소문자 구별하지 말라
        if(!preg_match('/^[0-9a-zA-Z\~\!\@\#\$\%\^\&\*\(\)]{7,}$/',$passwd)) { // 최소7자리 이상 허용 문자만 통과
            $this->popup('정보가 올바르지 않습니다');
        }

        $sql = "select code, id ";
        $sql.= "from memberdata where pw=md5('".$passwd."') and id= '".$userID."' ";
        if($result = mysqli_query($DB_CONNECT,$sql)) { //성공
            $row = mysqli_fetch_array($result);
            if($row == NULL) $this->popup('정보가 올바르지 않습니다');
                return $row;
            } else {
                $this->popup('정보가 올바르지 않습니다');
        }
    }
}

728x90
블로그 이미지

Link2Me

,

XML 데이터 생성하여 화면에 보여주거나, 파일로 저장하는 방법에 대한 함수를 시간을 많이 할애하고 테스트하고 적어둔다.

작업을 하다보니 XML 데이터의 칼럼수가 달라지는 경우 일일이 적어주는 것도 일이더라.

그래서 함수로 만들어서 사용하니 매우 편하다.

dbClass.php 에 대한 설명은 http://link2me.tistory.com/1110 참조하면 된다.


<?php
    include_once $_SERVER['DOCUMENT_ROOT'].'/db.info.php';
    require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
    require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/xmlClass.php';

    $conn = new MySQLDbClass(); // DB 함수
    $DB_CONNECT = $conn->isConnectDb($DB);

    // 화면에 출력할 칼럼 발췌
   $sql ="select (select classname from category where uid=d.cate1) as cat1,(select classname from category where uid=d.cate2) as cat2,subject,content from data d where is_direct=2 and is_checking=0";
   $result = mysql_query($sql,$DB_CONNECT);

    $c = new xmlcreateClass();
    $c->XML2View($result); // XML 데이터 화면 출력
    //$c->XML2File($result); // XML 데이터 파일 서버에 저장
    //$c->XMLDownload($result, 'myTest'); // XML 데이터 파일 PC에 저장

?>



<?php
class xmlcreateClass {

    // MySQL DB 자료를 column 개수, 게시물 총개수 만큼 자동으로 XML로 만들기
    function exportAsXML($result){
        $xml ='<?xml version="1.0" encoding="UTF-8" ?>'."\n";
        $xml.='<ListInfo>'."\n";
        while($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
            $xml.="<items>"."\n";
            foreach($row as $column => $value) {
                $xml.="<".$column."><![CDATA[".$value."]]></".$column.">"."\n";
            }
            $xml.="</items>"."\n";
        }
        $xml.='</ListInfo>';
        return $xml;
    }

    // XML 데이터를 모니터 화면으로 출력
    // $c->XML2View($result); // XML 데이터 화면 출력
    function XML2View($result) {
        header('Content-type: text/xml');
        echo $this->exportAsXML($result);
    }

    // XML 데이터를 파일로 서버 저장
    function XML2File($result) {
        $destination_path='files/';
        $xmlfile ='XMLSaveFile.xml';
        $filename = $destination_path . $xmlfile;

        @chmod($filename,0707);  // 파일의 소유권이 있는 경우에만 권한 변경

        $file = fopen($filename,"w");
        fwrite($file, $this->exportAsXML($result));
        fclose($file);

        echo '<script>alert("파일저장 완료");</script>';
    }

    // XML 생성 데이터를 PC에 파일로 저장
    function XMLDownload($result, $filename) {
        header("Content-type: application/vnd.ms-excel; charset=UTF-8");
        header("Content-Disposition: attachment; filename = ".$filename."_".date("Ymd").".xml");
        header("Content-Description: PHP5 Generated Data");
        header("Cache-Control: no-cache"); header("Pragma: no-cache");
        echo $this->exportAsXML($result);
        exit;
    }

}  // end of Class
?>

728x90
블로그 이미지

Link2Me

,

PHP 에서 XML 문서로 데이터 출력을 하는 방법에 대해 알아보자.


XML 문서 만들기의 규칙

- 모든 XML 문서들은 정확한 형식을 갖추어야 한다.

- 모든 태그들은 쌍(시작태그, 종료태그)을 이루어야 한다.


PHP XML Parser 는 두가지 종류가 있다.

SimpleXML Parser 와 XML expat Parser이다.

XML expat Parser 는 event 기반 parser 이다. (http://www.w3schools.com/php/php_xml_parser_expat.asp)

XML expat Parser 는 XML 파일 데이터가 많은 경우에 효과적이다.

XML Expat Parser functions 의 구성요소는 3개의 이벤트로 구성되어 있다고 볼 수 있다.

- Start element: from
- Start CDATA section, value: Jani
- Close element: from


<?php

// 1. DB 접속 경로 지정하여 DB를 읽어들인다.
// 2. 읽어들일 XML 파일의 경로를 지정한다. $readFile
// 3. 읽어들일 파일이 XML 파일인지 여부를 검사한다.
// 4. 초기 변수를 선언한다.
// 5. XML parser 를 생성하고 읽어들인 XML 파일을 파싱처리하여 DB에 저장한다.
$parser=xml_parser_create(); // XML parser 생성

// element handler 등록, start/stop 은 함수명
xml_set_element_handler($parser,"start","stop");

// data handler 등록, char 는 함수명
xml_set_character_data_handler($parser,"char");

//Open XML file
$fp=fopen($readFile,"r");

//Read data
while (!feof($fp)) { // 파일의 마지막까지
    $data = fgets($fp);  // 파일을 한줄씩 읽어들인다.
    xml_parse($parser,$data,feof($fp)) or
    die (sprintf("XML Error: %s at line %d", xml_error_string(xml_get_error_code($parser)),
    xml_get_current_line_number($parser)));
}

//Free the XML parser
xml_parser_free($parser);

//Function to use at the start of an element
function start($parser,$element_name,$element_attrs) {
    global $parsedata;
    $parsedata = "";
}

//Function to use at the end of an element
function stop($parser,$element_name) {
    switch($element_name) {
        case "user_id":
            $user_id = $parsedata
            break;
        case "user_email":
            $user_email = $parsedata
            break;
        case "content":
            $content = $parsedata
            break;
        case "item":
            // <item> </item> 으로 하나의 자료가 끝나는 시점이므로 parse data 를 DB에 저장 처리
            // DB 저장시 key 값 기준으로 데이터 중복체크하여 insert, update 처리
            break;
    }
}

//Function to use when finding character data
function char($parser,$data) {
    global $parsedata;
    $parsedata = $data;
}

?>


728x90
블로그 이미지

Link2Me

,

if(!isset($_SESSION['userID']) || empty($_SESSION['userID']) || empty($_GET['uid'])){
    // 세션 및 접속 조건을 만족하지 못하면 (비정상접속)
    // 둘중의 하나를 적어준다.
    echo ("<script>alert('정상적인 접속이 아닙니다');window.top.location.replace('index.php');</script>");
    //echo ("<meta http-equiv='Refresh' content='0; URL=index.php'>");
    exit;
}

// 접속 IP 체크는 필요한 경우에 코드를 추가한다.


require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; // 데이터베이스 접속


728x90
블로그 이미지

Link2Me

,